119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * htree.c --- hash tree routines 33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 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> 203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#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" 263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "uuid/uuid.h" 273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "e2p/e2p.h" 2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic FILE *pager; 3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, 3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, 3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info * rootnode, 3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk, char *buf) 3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t errcode; 3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dir_entry *dirent; 3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int thislen, col = 0; 3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned int offset = 0; 4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char name[EXT2_NAME_LEN + 1]; 4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char tmp[EXT2_NAME_LEN + 16]; 4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t pblk; 433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2_dirhash_t hash, minor_hash; 443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned int rec_len; 4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int hash_alg; 463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_leaf_node", errcode, 5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while mapping logical block %u\n", blk); 5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("Reading directory block %lu, phys %lu\n", 553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (unsigned long) blk, (unsigned long) pblk); 5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0); 5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_leaf_node", errcode, 593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "while reading block %lu (%lu)\n", 603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (unsigned long) blk, (unsigned long) pblk); 6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_alg = rootnode->hash_version; 6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((hash_alg <= EXT2_HASH_TEA) && 6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_alg += 3; 6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (offset < fs->blocksize) { 6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dirent = (struct ext2_dir_entry *) (buf + offset); 703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode = ext2fs_get_rec_len(fs, dirent, &rec_len); 713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (errcode) { 723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt com_err("htree_dump_leaf_inode", errcode, 733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "while getting rec_len for block %lu", 743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (unsigned long) blk); 753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return; 763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (((offset + rec_len) > fs->blocksize) || 783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (rec_len < 8) || 793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ((rec_len % 4) != 0) || 803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) { 8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Corrupted directory block (%u)!\n", blk); 8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? 8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (dirent->name_len & 0xFF) : EXT2_NAME_LEN; 8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project strncpy(name, dirent->name, thislen); 8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project name[thislen] = '\0'; 8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = ext2fs_dirhash(hash_alg, name, 8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project thislen, fs->super->s_hash_seed, 903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt &hash, &minor_hash); 9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) 9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_leaf_node", errcode, 9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while calculating hash"); 943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt sprintf(tmp, "%u 0x%08x-%08x (%d) %s ", dirent->inode, 953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt hash, minor_hash, rec_len, name); 9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project thislen = strlen(tmp); 9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (col + thislen > 80) { 9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\n"); 9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project col = 0; 10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "%s", tmp); 10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project col += thislen; 1033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt offset += rec_len; 10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\n"); 10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, 11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info * rootnode, 11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk, char *buf, int level); 11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, 11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, 11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info * rootnode, 1183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct ext2_dx_entry *ent, 11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf, int level) 12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_countlimit limit; 12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_entry e; 12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int hash, i; 1243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project limit = *((struct ext2_dx_countlimit *) ent); 12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project limit.count = ext2fs_le16_to_cpu(limit.count); 12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project limit.limit = ext2fs_le16_to_cpu(limit.limit); 12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Number of entries (count): %d\n", limit.count); 13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Number of entries (limit): %d\n", limit.limit); 13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < limit.count; i++) { 13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash = i ? ext2fs_le32_to_cpu(ent[i].hash) : 0; 13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Entry #%d: Hash 0x%08x%s, block %u\n", i, 13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash, (hash & 1) ? " (**)" : "", 13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_le32_to_cpu(ent[i].block)); 13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\n"); 14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < limit.count; i++) { 14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e.hash = ext2fs_le32_to_cpu(ent[i].hash); 14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e.block = ext2fs_le32_to_cpu(ent[i].block); 14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Entry #%d: Hash 0x%08x, block %u\n", i, 14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project i ? e.hash : 0, e.block); 14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (level) 14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project htree_dump_int_block(fs, ino, inode, rootnode, 14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e.block, buf, level-1); 15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project htree_dump_leaf_node(fs, ino, inode, rootnode, 15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e.block, buf); 15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "---------------------\n"); 15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, 16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info * rootnode, 16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk, char *buf, int level) 16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *cbuf; 16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t errcode; 16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t pblk; 16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project cbuf = malloc(fs->blocksize); 16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!cbuf) { 16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Couldn't allocate child block.\n"); 17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 1723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_int_block", errcode, 17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while mapping logical block %u\n", blk); 17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = io_channel_read_blk(current_fs->io, pblk, 1, buf); 18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("htree_dump_int_block", errcode, 18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while reading block %u\n", blk); 18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project htree_dump_int_node(fs, ino, inode, rootnode, 18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (struct ext2_dx_entry *) (buf+8), 18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project cbuf, level); 19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project free(cbuf); 19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid do_htree_dump(int argc, char *argv[]) 19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t ino; 19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int c; 20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int long_opt = 0; 2023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt blk_t blk; 20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf = NULL; 20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_root_info *rootnode; 20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_entry *ent; 20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dx_countlimit *limit; 20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t errcode; 20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (check_fs_open(argv[0])) 21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pager = open_pager(); 21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project reset_getopt(); 21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while ((c = getopt (argc, argv, "l")) != EOF) { 21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project switch (c) { 21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project case 'l': 21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project long_opt++; 21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project default: 22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto print_usage; 22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (argc > optind+1) { 22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project print_usage: 22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(0, 0, "Usage: htree_dump [-l] file"); 22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (argc == optind) 23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ino = cwd; 23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ino = string_to_inode(argv[optind]); 23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!ino) 23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (debugfs_read_inode(ino, &inode, argv[1])) 23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!LINUX_S_ISDIR(inode.i_mode)) { 24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], 0, "Not a directory"); 24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 2453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((inode.i_flags & EXT2_BTREE_FL) == 0) { 24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], 0, "Not a hash-indexed directory"); 24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project buf = malloc(2*current_fs->blocksize); 25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!buf) { 25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], 0, "Couldn't allocate htree buffer"); 25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode = ext2fs_bmap(current_fs, ino, &inode, buf, 0, 0, &blk); 2583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (errcode) { 2593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt com_err("do_htree_block", errcode, 2603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "while mapping logical block 0\n"); 2613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto errout; 2623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode = io_channel_read_blk(current_fs->io, blk, 26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1, buf); 26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], errcode, "Error reading root node"); 26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project rootnode = (struct ext2_dx_root_info *) (buf + 24); 27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "Root node dump:\n"); 27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); 27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); 27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Info length: %d\n", rootnode->info_length); 27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); 27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); 27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); 28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project limit = (struct ext2_dx_countlimit *) ent; 28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, 28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project buf + current_fs->blocksize, 28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project rootnode->indirect_levels); 28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 2883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt free(buf); 28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close_pager(pager); 29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function prints the hash of a given file. 29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid do_dx_hash(int argc, char *argv[]) 29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_dirhash_t hash, minor_hash; 29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t err; 29919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int c; 30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int hash_version = 0; 30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project __u32 hash_seed[4]; 3023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0; 30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project reset_getopt(); 3063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt while ((c = getopt (argc, argv, "h:s:")) != EOF) { 30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project switch (c) { 30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project case 'h': 3093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt hash_version = e2p_string2hash(optarg); 3103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (hash_version < 0) 3113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt hash_version = atoi(optarg); 3123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt break; 3133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt case 's': 3143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (uuid_parse(optarg, (unsigned char *) hash_seed)) { 3153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fprintf(stderr, "Invalid UUID format: %s\n", 3163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt optarg); 3173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return; 3183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project default: 32119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto print_usage; 32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 32319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 32419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (optind != argc-1) { 32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project print_usage: 3263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt com_err(argv[0], 0, "usage: dx_hash [-h hash_alg] " 3273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "[-s hash_seed] filename"); 32819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 32919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 33019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]), 33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash_seed, &hash, &minor_hash); 33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (err) { 33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], err, "while caclulating hash"); 33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind], 33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project hash, minor_hash); 33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Search for particular directory entry (useful for debugging very 34219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * large hash tree directories that have lost some blocks from the 34319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * btree index). 34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 34519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct process_block_struct { 34619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *search_name; 34719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf; 34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int len; 34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}; 35019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 3523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt e2_blkcnt_t blockcnt, blk_t ref_blk, 35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int ref_offset, void *priv_data); 35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid do_dirsearch(int argc, char *argv[]) 35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 35719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t inode; 35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct process_block_struct pb; 3593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 36019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (check_fs_open(argv[0])) 36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 36319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (argc != 3) { 36419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(0, 0, "Usage: dirsearch dir filename"); 36519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 36619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 36719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 36819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode = string_to_inode(argv[1]); 36919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!inode) 37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pb.buf = malloc(current_fs->blocksize); 37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!pb.buf) { 37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("dirsearch", 0, "Couldn't allocate buffer"); 37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pb.search_name = argv[2]; 37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pb.len = strlen(pb.search_name); 3793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_block_iterate2(current_fs, inode, BLOCK_FLAG_READ_ONLY, 0, 3813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt search_dir_block, &pb); 38219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project free(pb.buf); 38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 38619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 38719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 3883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt e2_blkcnt_t blockcnt, 38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t ref_blk EXT2FS_ATTR((unused)), 39019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int ref_offset EXT2FS_ATTR((unused)), 39119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void *priv_data) 39219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 39319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct process_block_struct *p; 39419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_dir_entry *dirent; 39519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t errcode; 39619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned int offset = 0; 3973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned int rec_len; 39819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 39919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blockcnt < 0) 40019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 40119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 40219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project p = (struct process_block_struct *) priv_data; 40319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 40419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode = io_channel_read_blk(current_fs->io, *blocknr, 1, p->buf); 40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (errcode) { 40619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err("search_dir_block", errcode, 40719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "while reading block %lu", (unsigned long) *blocknr); 40819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 40919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 41019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 41119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (offset < fs->blocksize) { 41219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dirent = (struct ext2_dir_entry *) (p->buf + offset); 4133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode = ext2fs_get_rec_len(fs, dirent, &rec_len); 4143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (errcode) { 4153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt com_err("htree_dump_leaf_inode", errcode, 4163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "while getting rec_len for block %lu", 4173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (unsigned long) *blocknr); 4183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return BLOCK_ABORT; 4193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 42019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (dirent->inode && 4213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt p->len == (dirent->name_len & 0xFF) && 42219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project strncmp(p->search_name, dirent->name, 42319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project p->len) == 0) { 42419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("Entry found at logical block %lld, " 42519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project "phys %u, offset %u\n", (long long)blockcnt, 42619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *blocknr, offset); 42719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("offset %u\n", offset); 42819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 42919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 4303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt offset += rec_len; 43119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 43219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 43319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 43419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 435