htree.c revision 19dacda2b02bb08c0ffb649f84526b249c749279
119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * htree.c --- hash tree routines 319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 2002 Theodore Ts'o. This file may be redistributed 519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * under the terms of the GNU Public License. 619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h> 919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h> 1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdlib.h> 1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <ctype.h> 1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h> 1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <time.h> 1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_ERRNO_H 1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h> 1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h> 1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_GETOPT_H 1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <getopt.h> 2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else 2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectextern int optind; 2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectextern char *optarg; 2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "debugfs.h" 2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic FILE *pager; 2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, 3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, 3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info * rootnode, 3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk, char *buf) 3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t errcode; 3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dir_entry *dirent; 3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int thislen, col = 0; 3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned int offset = 0; 3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char name[EXT2_NAME_LEN + 1]; 3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char tmp[EXT2_NAME_LEN + 16]; 4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t pblk; 4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_dirhash_t hash; 4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int hash_alg; 4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_leaf_node", errcode, 4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while mapping logical block %u\n", blk); 4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0); 5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_leaf_node", errcode, 5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while reading block %u\n", blk); 5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_alg = rootnode->hash_version; 5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((hash_alg <= EXT2_HASH_TEA) && 5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_alg += 3; 6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (offset < fs->blocksize) { 6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dirent = (struct ext2_dir_entry *) (buf + offset); 6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (((offset + dirent->rec_len) > fs->blocksize) || 6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (dirent->rec_len < 8) || 6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ((dirent->rec_len % 4) != 0) || 6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { 6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Corrupted directory block (%u)!\n", blk); 6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? 7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (dirent->name_len & 0xFF) : EXT2_NAME_LEN; 7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project strncpy(name, dirent->name, thislen); 7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project name[thislen] = '\0'; 7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = ext2fs_dirhash(hash_alg, name, 7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project thislen, fs->super->s_hash_seed, 7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project &hash, 0); 7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) 7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_leaf_node", errcode, 8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while calculating hash"); 8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sprintf(tmp, "%u 0x%08x (%d) %s ", dirent->inode, 8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash, dirent->rec_len, name); 8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project thislen = strlen(tmp); 8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (col + thislen > 80) { 8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\n"); 8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project col = 0; 8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "%s", tmp); 8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project col += thislen; 9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset += dirent->rec_len; 9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\n"); 9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, 9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info * rootnode, 9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk, char *buf, int level); 10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, 10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, 10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info * rootnode, 10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_entry *ent, 10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf, int level) 10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_countlimit limit; 10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_entry e; 11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int hash, i; 11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project limit = *((struct ext2_dx_countlimit *) ent); 11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project limit.count = ext2fs_le16_to_cpu(limit.count); 11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project limit.limit = ext2fs_le16_to_cpu(limit.limit); 11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Number of entries (count): %d\n", limit.count); 11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Number of entries (limit): %d\n", limit.limit); 11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < limit.count; i++) { 12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash = i ? ext2fs_le32_to_cpu(ent[i].hash) : 0; 12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Entry #%d: Hash 0x%08x%s, block %u\n", i, 12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash, (hash & 1) ? " (**)" : "", 12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_le32_to_cpu(ent[i].block)); 12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\n"); 12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < limit.count; i++) { 13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e.hash = ext2fs_le32_to_cpu(ent[i].hash); 13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e.block = ext2fs_le32_to_cpu(ent[i].block); 13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Entry #%d: Hash 0x%08x, block %u\n", i, 13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project i ? e.hash : 0, e.block); 13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (level) 13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project htree_dump_int_block(fs, ino, inode, rootnode, 13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e.block, buf, level-1); 13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project htree_dump_leaf_node(fs, ino, inode, rootnode, 13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e.block, buf); 14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "---------------------\n"); 14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, 14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info * rootnode, 14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk, char *buf, int level) 14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *cbuf; 15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t errcode; 15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t pblk; 15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project cbuf = malloc(fs->blocksize); 15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!cbuf) { 15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Couldn't allocate child block.\n"); 15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_int_block", errcode, 16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while mapping logical block %u\n", blk); 16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = io_channel_read_blk(current_fs->io, pblk, 1, buf); 16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_int_block", errcode, 17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while reading block %u\n", blk); 17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project htree_dump_int_node(fs, ino, inode, rootnode, 17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (struct ext2_dx_entry *) (buf+8), 17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project cbuf, level); 17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project free(cbuf); 17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid do_htree_dump(int argc, char *argv[]) 18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t ino; 18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int c; 18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int long_opt = 0; 18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf = NULL; 19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info *rootnode; 19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_entry *ent; 19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_countlimit *limit; 19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t errcode; 19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (check_fs_open(argv[0])) 19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pager = open_pager(); 19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project reset_getopt(); 20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while ((c = getopt (argc, argv, "l")) != EOF) { 20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project switch (c) { 20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project case 'l': 20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project long_opt++; 20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project default: 20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto print_usage; 20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (argc > optind+1) { 21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project print_usage: 21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(0, 0, "Usage: htree_dump [-l] file"); 21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (argc == optind) 21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ino = cwd; 21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ino = string_to_inode(argv[optind]); 22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!ino) 22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (debugfs_read_inode(ino, &inode, argv[1])) 22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!LINUX_S_ISDIR(inode.i_mode)) { 22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], 0, "Not a directory"); 22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((inode.i_flags & EXT2_BTREE_FL) == 0) { 23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], 0, "Not a hash-indexed directory"); 23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project buf = malloc(2*current_fs->blocksize); 23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!buf) { 23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], 0, "Couldn't allocate htree buffer"); 24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = io_channel_read_blk(current_fs->io, inode.i_block[0], 24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1, buf); 24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], errcode, "Error reading root node"); 24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project rootnode = (struct ext2_dx_root_info *) (buf + 24); 25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Root node dump:\n"); 25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); 25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); 25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Info length: %d\n", rootnode->info_length); 25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); 25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); 25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); 26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project limit = (struct ext2_dx_countlimit *) ent; 26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, 26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project buf + current_fs->blocksize, 26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project rootnode->indirect_levels); 26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (buf) 26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project free(buf); 26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close_pager(pager); 27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function prints the hash of a given file. 27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid do_dx_hash(int argc, char *argv[]) 27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_dirhash_t hash, minor_hash; 27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t err; 27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int c; 28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int hash_version = 0; 28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project __u32 hash_seed[4]; 28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0; 28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project reset_getopt(); 28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while ((c = getopt (argc, argv, "h:")) != EOF) { 28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project switch (c) { 28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project case 'h': 28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_version = atoi(optarg); 29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project default: 29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto print_usage; 29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (optind != argc-1) { 29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project print_usage: 29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], 0, "usage: dx_hash filename"); 29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 29919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]), 30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_seed, &hash, &minor_hash); 30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (err) { 30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], err, "while caclulating hash"); 30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 30619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind], 30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash, minor_hash); 30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 30919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 31019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 31119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Search for particular directory entry (useful for debugging very 31219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * large hash tree directories that have lost some blocks from the 31319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * btree index). 31419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 31519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct process_block_struct { 31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *search_name; 31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf; 31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int len; 31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}; 32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 32119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2_blkcnt_t blockcnt, blk_t ref_blk, 32319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int ref_offset, void *priv_data); 32419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid do_dirsearch(int argc, char *argv[]) 32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 32719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t inode; 32819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct process_block_struct pb; 32919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 33019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (check_fs_open(argv[0])) 33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (argc != 3) { 33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(0, 0, "Usage: dirsearch dir filename"); 33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode = string_to_inode(argv[1]); 33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!inode) 34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 34219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pb.buf = malloc(current_fs->blocksize); 34319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!pb.buf) { 34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("dirsearch", 0, "Couldn't allocate buffer"); 34519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 34619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 34719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pb.search_name = argv[2]; 34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pb.len = strlen(pb.search_name); 34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_block_iterate2(current_fs, inode, 0, 0, search_dir_block, &pb); 35119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project free(pb.buf); 35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 35719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2_blkcnt_t blockcnt, 35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t ref_blk EXT2FS_ATTR((unused)), 35919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int ref_offset EXT2FS_ATTR((unused)), 36019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void *priv_data) 36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct process_block_struct *p; 36319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dir_entry *dirent; 36419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t errcode; 36519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned int offset = 0; 36619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 36719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blockcnt < 0) 36819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 36919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project p = (struct process_block_struct *) priv_data; 37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = io_channel_read_blk(current_fs->io, *blocknr, 1, p->buf); 37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("search_dir_block", errcode, 37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while reading block %lu", (unsigned long) *blocknr); 37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 37919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (offset < fs->blocksize) { 38019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dirent = (struct ext2_dir_entry *) (p->buf + offset); 38119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 38219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (dirent->inode && 38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project p->len == (dirent->name_len & 0xFF) && 38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project strncmp(p->search_name, dirent->name, 38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project p->len) == 0) { 38619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("Entry found at logical block %lld, " 38719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "phys %u, offset %u\n", (long long)blockcnt, 38819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *blocknr, offset); 38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("offset %u\n", offset); 39019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 39119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 39219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset += dirent->rec_len; 39319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 39419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 39519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 39619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 397