htree.c revision 45e338f5332a54295893dba2e32cc093d1316f60
1df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 2df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * htree.c --- hash tree routines 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 4df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * Copyright (C) 2002 Theodore Ts'o. This file may be redistributed 5df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * under the terms of the GNU Public License. 6df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 7df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 8df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <stdio.h> 9df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <unistd.h> 10df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <stdlib.h> 11df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <ctype.h> 12df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <string.h> 13df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <time.h> 14df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#ifdef HAVE_ERRNO_H 15df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <errno.h> 16df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#endif 17df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <sys/types.h> 18df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#ifdef HAVE_GETOPT_H 19df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include <getopt.h> 20efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else 21df614db6ef79c767745b8154c26d69398b571605Theodore Ts'oextern int optind; 22df614db6ef79c767745b8154c26d69398b571605Theodore Ts'oextern char *optarg; 23df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#endif 24df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 25df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include "debugfs.h" 26df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 27df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic FILE *pager; 28df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 29df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, 30df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 313e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 32df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t blk, char *buf) 33df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 34df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 35df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dir_entry *dirent; 36544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int thislen, col = 0; 37544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 38b772900b4bcff407c883b7bd8419af56be0a9823Brian Behlendorf char name[EXT2_NAME_LEN + 1]; 39df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char tmp[EXT2_NAME_LEN + 16]; 40df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t pblk; 41226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o ext2_dirhash_t hash, minor_hash; 425dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o int rec_len, hash_alg; 43efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 44df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 45df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 46df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 478deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato "while mapping logical block %u\n", blk); 48df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 49df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 50df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 51226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o printf("Reading directory block %lu, phys %lu\n", blk, pblk); 528132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0); 53df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 54df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 55226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o "while reading block %lu (%lu)\n", blk, pblk); 56df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 57df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 58f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o hash_alg = rootnode->hash_version; 59f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o if ((hash_alg <= EXT2_HASH_TEA) && 60f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 61f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o hash_alg += 3; 62df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 63df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while (offset < fs->blocksize) { 64df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o dirent = (struct ext2_dir_entry *) (buf + offset); 655dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o rec_len = (dirent->rec_len || fs->blocksize < 65536) ? 665dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o dirent->rec_len : 65536; 675dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (((offset + rec_len) > fs->blocksize) || 685dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (rec_len < 8) || 695dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o ((rec_len % 4) != 0) || 705dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (((dirent->name_len & 0xFF)+8) > rec_len)) { 718deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato fprintf(pager, "Corrupted directory block (%u)!\n", blk); 72df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o break; 73df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 74df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? 75df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o (dirent->name_len & 0xFF) : EXT2_NAME_LEN; 76df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o strncpy(name, dirent->name, thislen); 77df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o name[thislen] = '\0'; 78f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o errcode = ext2fs_dirhash(hash_alg, name, 793e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o thislen, fs->super->s_hash_seed, 80226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o &hash, &minor_hash); 8152783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o if (errcode) 8252783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 8352783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o "while calculating hash"); 84226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o sprintf(tmp, "%u 0x%08x-%08x (%d) %s ", dirent->inode, 855dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o hash, minor_hash, rec_len, name); 86df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o thislen = strlen(tmp); 87df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (col + thislen > 80) { 88df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 89df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o col = 0; 90df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 91df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "%s", tmp); 92df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o col += thislen; 935dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o offset += rec_len; 94df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 95df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 96df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 97df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 98df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 99df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 100df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 1013e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 102df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t blk, char *buf, int level); 103df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 104df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 105df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, 106df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 1073e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 108efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o struct ext2_dx_entry *ent, 109df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *buf, int level) 110df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 111621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o struct ext2_dx_countlimit limit; 112621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o struct ext2_dx_entry e; 11342e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o int hash, i; 114efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 115df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 116621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit = *((struct ext2_dx_countlimit *) ent); 117621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit.count = ext2fs_le16_to_cpu(limit.count); 118621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit.limit = ext2fs_le16_to_cpu(limit.limit); 119df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 120621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o fprintf(pager, "Number of entries (count): %d\n", limit.count); 121621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o fprintf(pager, "Number of entries (limit): %d\n", limit.limit); 122df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 12342e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o for (i=0; i < limit.count; i++) { 12442e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o hash = i ? ext2fs_le32_to_cpu(ent[i].hash) : 0; 125d0ff90d5202428583c78a60c3042e7b60d88bc45Eric Sandeen fprintf(pager, "Entry #%d: Hash 0x%08x%s, block %u\n", i, 12642e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o hash, (hash & 1) ? " (**)" : "", 127621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o ext2fs_le32_to_cpu(ent[i].block)); 12842e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o } 129df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 130df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 131df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 132621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o for (i=0; i < limit.count; i++) { 133621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.hash = ext2fs_le32_to_cpu(ent[i].hash); 134621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block = ext2fs_le32_to_cpu(ent[i].block); 1358deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato fprintf(pager, "Entry #%d: Hash 0x%08x, block %u\n", i, 136621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o i ? e.hash : 0, e.block); 137df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (level) 1383e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_block(fs, ino, inode, rootnode, 139621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block, buf, level-1); 140df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o else 1413e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_leaf_node(fs, ino, inode, rootnode, 142621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block, buf); 143df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 144df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 145df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "---------------------\n"); 146df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 147df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 148df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 149df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 1503e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 151df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t blk, char *buf, int level) 152df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 153df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *cbuf; 154df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 155df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t pblk; 156df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 157df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o cbuf = malloc(fs->blocksize); 158df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!cbuf) { 159df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Couldn't allocate child block.\n"); 160df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 161df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 162efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 163df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 164df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 165df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_int_block", errcode, 1668deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato "while mapping logical block %u\n", blk); 16789456558df36b22ca664ead88e768d6a486c7cefBrian Behlendorf goto errout; 168df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 169df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 170df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, pblk, 1, buf); 171df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 172df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_int_block", errcode, 1738deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato "while reading block %u\n", blk); 17489456558df36b22ca664ead88e768d6a486c7cefBrian Behlendorf goto errout; 175df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 176df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 1773e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_node(fs, ino, inode, rootnode, 178503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o (struct ext2_dx_entry *) (buf+8), 179df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o cbuf, level); 18089456558df36b22ca664ead88e768d6a486c7cefBrian Behlendorferrout: 181df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(cbuf); 182df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 183df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 184df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 185df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 186df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_htree_dump(int argc, char *argv[]) 187df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 188df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2_ino_t ino; 189df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode inode; 1903e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o int c; 191d904dd2ac0240c2a871ca742321c0ea65f493284Theodore Ts'o int long_opt = 0; 192226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o blk_t blk; 1933e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o char *buf = NULL; 1943e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info *rootnode; 195df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_entry *ent; 196df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_countlimit *limit; 197df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 198df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 199df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (check_fs_open(argv[0])) 200df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 201df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 202df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pager = open_pager(); 203df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 20488494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o reset_getopt(); 205df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while ((c = getopt (argc, argv, "l")) != EOF) { 206df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o switch (c) { 207df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o case 'l': 208df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o long_opt++; 209df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o break; 21049c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o default: 21149c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o goto print_usage; 212df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 213df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 214df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 215df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc > optind+1) { 21649c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o print_usage: 217df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(0, 0, "Usage: htree_dump [-l] file"); 218155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 219df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 220df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 221df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc == optind) 222df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ino = cwd; 223df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o else 224df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ino = string_to_inode(argv[optind]); 225df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!ino) 226155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 227df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 228df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (debugfs_read_inode(ino, &inode, argv[1])) 229155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 230df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 231df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!LINUX_S_ISDIR(inode.i_mode)) { 232df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Not a directory"); 233155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 234df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 235efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 236df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if ((inode.i_flags & EXT2_BTREE_FL) == 0) { 237df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Not a hash-indexed directory"); 238155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 239df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 240df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 241df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o buf = malloc(2*current_fs->blocksize); 242df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!buf) { 243df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Couldn't allocate htree buffer"); 244155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 245df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 246df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 247226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o errcode = ext2fs_bmap(current_fs, ino, &inode, buf, 0, 0, &blk); 248226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o if (errcode) { 249226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o com_err("do_htree_block", errcode, 250226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o "while mapping logical block 0\n"); 251226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o goto errout; 252226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o } 253226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o 254efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, blk, 255df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 1, buf); 256df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 257df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], errcode, "Error reading root node"); 258df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o goto errout; 259df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 260df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2613e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o rootnode = (struct ext2_dx_root_info *) (buf + 24); 262df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 263df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Root node dump:\n"); 2648deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); 2653e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); 2663e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Info length: %d\n", rootnode->info_length); 2673e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); 2683e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); 269df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2703e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); 271df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o limit = (struct ext2_dx_countlimit *) ent; 272df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2733e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, 274df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o buf + current_fs->blocksize, 2753e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o rootnode->indirect_levels); 276df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 277df614db6ef79c767745b8154c26d69398b571605Theodore Ts'oerrout: 27845e338f5332a54295893dba2e32cc093d1316f60Jim Meyering free(buf); 279df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o close_pager(pager); 280df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 281df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 282df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 283df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * This function prints the hash of a given file. 284df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 285df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_dx_hash(int argc, char *argv[]) 286df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 287503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o ext2_dirhash_t hash, minor_hash; 28852783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o errcode_t err; 289503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o int c; 290503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o int hash_version = 0; 291503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o __u32 hash_seed[4]; 292efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 293503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0; 29488494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o 29588494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o reset_getopt(); 296f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o while ((c = getopt (argc, argv, "h:s:")) != EOF) { 297503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o switch (c) { 298503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o case 'h': 299f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o hash_version = e2p_string2hash(optarg); 300f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o if (hash_version < 0) 301f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o hash_version = atoi(optarg); 302f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o break; 303f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o case 's': 304f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o if (uuid_parse(optarg, hash_seed)) { 305f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o fprintf(stderr, "Invalid UUID format: %s\n", 306f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o optarg); 307f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o return; 308f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o } 309503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o break; 31049c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o default: 31149c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o goto print_usage; 312503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o } 313503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o } 314503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o if (optind != argc-1) { 31549c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o print_usage: 316f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o com_err(argv[0], 0, "usage: dx_hash [-h hash_alg] " 317f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o "[-s hash_seed] filename"); 318df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 319df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 320503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]), 321503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_seed, &hash, &minor_hash); 32252783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o if (err) { 32352783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o com_err(argv[0], err, "while caclulating hash"); 32452783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o return; 32552783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o } 326503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind], 327503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash, minor_hash); 328df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 329df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 330df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 331df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * Search for particular directory entry (useful for debugging very 332df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * large hash tree directories that have lost some blocks from the 333df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * btree index). 334df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 335df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostruct process_block_struct { 336df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *search_name; 337df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *buf; 338df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int len; 339df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o}; 340df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 341df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 342efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e2_blkcnt_t blockcnt, blk_t ref_blk, 343df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int ref_offset, void *priv_data); 344df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 345df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_dirsearch(int argc, char *argv[]) 346df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 347df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2_ino_t inode; 348df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct process_block_struct pb; 349efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 350df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (check_fs_open(argv[0])) 351df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 352df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 353df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc != 3) { 354df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(0, 0, "Usage: dirsearch dir filename"); 355df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 356df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 357df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 358df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o inode = string_to_inode(argv[1]); 359df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!inode) 360df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 361df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 362df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.buf = malloc(current_fs->blocksize); 363df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!pb.buf) { 364df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("dirsearch", 0, "Couldn't allocate buffer"); 365df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 366df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 367df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.search_name = argv[2]; 368df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.len = strlen(pb.search_name); 369efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 37043323be95742298b8229be728c3812e95c90629cTheodore Ts'o ext2fs_block_iterate2(current_fs, inode, BLOCK_FLAG_READ_ONLY, 0, 37143323be95742298b8229be728c3812e95c90629cTheodore Ts'o search_dir_block, &pb); 372df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 373df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(pb.buf); 374df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 375df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 376df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 377df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 378efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e2_blkcnt_t blockcnt, 379544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o blk_t ref_blk EXT2FS_ATTR((unused)), 380544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 381544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o void *priv_data) 382df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 383df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct process_block_struct *p; 384df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dir_entry *dirent; 385df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 386544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 3875dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o int rec_len; 388df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 389df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (blockcnt < 0) 390df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return 0; 391df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 392df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p = (struct process_block_struct *) priv_data; 393df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 394df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, *blocknr, 1, p->buf); 395df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 396df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("search_dir_block", errcode, 397544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o "while reading block %lu", (unsigned long) *blocknr); 398df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return BLOCK_ABORT; 399df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 400df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 401df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while (offset < fs->blocksize) { 402df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o dirent = (struct ext2_dir_entry *) (p->buf + offset); 4035dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o rec_len = (dirent->rec_len || fs->blocksize < 65536) ? 4045dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o dirent->rec_len : 65536; 405df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (dirent->inode && 406efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o p->len == (dirent->name_len & 0xFF) && 407df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o strncmp(p->search_name, dirent->name, 408df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p->len) == 0) { 409df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o printf("Entry found at logical block %lld, " 410de8f3a76218255e443ba57dec5d74850180fa75dAndreas Dilger "phys %u, offset %u\n", (long long)blockcnt, 411df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o *blocknr, offset); 4128deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("offset %u\n", offset); 413df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return BLOCK_ABORT; 414df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 4155dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o offset += rec_len; 416df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 417df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return 0; 418df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 419df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 420