htree.c revision f77704e416fca7dbe4cc91abba674d2ae3c14f6f
1df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 2df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * htree.c --- hash tree routines 3df614db6ef79c767745b8154c26d69398b571605Theodore 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> 20df614db6ef79c767745b8154c26d69398b571605Theodore 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; 38df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char name[EXT2_NAME_LEN]; 39df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char tmp[EXT2_NAME_LEN + 16]; 40df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t pblk; 4152783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o ext2_dirhash_t hash; 42f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o int hash_alg; 43df614db6ef79c767745b8154c26d69398b571605Theodore 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 518132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0); 52df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 53df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 548deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato "while reading block %u\n", blk); 55df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 56df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 57f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o hash_alg = rootnode->hash_version; 58f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o if ((hash_alg <= EXT2_HASH_TEA) && 59f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 60f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o hash_alg += 3; 61df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 62df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while (offset < fs->blocksize) { 63df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o dirent = (struct ext2_dir_entry *) (buf + offset); 64df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (((offset + dirent->rec_len) > fs->blocksize) || 65df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o (dirent->rec_len < 8) || 66df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ((dirent->rec_len % 4) != 0) || 67df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { 688deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato fprintf(pager, "Corrupted directory block (%u)!\n", blk); 69df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o break; 70df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 71df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? 72df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o (dirent->name_len & 0xFF) : EXT2_NAME_LEN; 73df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o strncpy(name, dirent->name, thislen); 74df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o name[thislen] = '\0'; 75f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o errcode = ext2fs_dirhash(hash_alg, name, 763e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o thislen, fs->super->s_hash_seed, 77503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o &hash, 0); 7852783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o if (errcode) 7952783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 8052783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o "while calculating hash"); 81df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o sprintf(tmp, "%u 0x%08x (%d) %s ", dirent->inode, 8252783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o hash, dirent->rec_len, name); 83df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o thislen = strlen(tmp); 84df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (col + thislen > 80) { 85df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 86df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o col = 0; 87df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 88df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "%s", tmp); 89df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o col += thislen; 90df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o offset += dirent->rec_len; 91df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 92df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 93df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 94df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 95df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 96df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 97df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 983e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 99df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t blk, char *buf, int level); 100df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 101df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 102df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, 103df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 1043e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 105df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_entry *ent, 106df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *buf, int level) 107df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 108621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o struct ext2_dx_countlimit limit; 109621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o struct ext2_dx_entry e; 11042e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o int hash, i; 111621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o 112df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 113621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit = *((struct ext2_dx_countlimit *) ent); 114621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit.count = ext2fs_le16_to_cpu(limit.count); 115621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit.limit = ext2fs_le16_to_cpu(limit.limit); 116df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 117621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o fprintf(pager, "Number of entries (count): %d\n", limit.count); 118621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o fprintf(pager, "Number of entries (limit): %d\n", limit.limit); 119df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 12042e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o for (i=0; i < limit.count; i++) { 12142e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o hash = i ? ext2fs_le32_to_cpu(ent[i].hash) : 0; 122d0ff90d5202428583c78a60c3042e7b60d88bc45Eric Sandeen fprintf(pager, "Entry #%d: Hash 0x%08x%s, block %u\n", i, 12342e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o hash, (hash & 1) ? " (**)" : "", 124621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o ext2fs_le32_to_cpu(ent[i].block)); 12542e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o } 126df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 127df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 128df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 129621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o for (i=0; i < limit.count; i++) { 130621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.hash = ext2fs_le32_to_cpu(ent[i].hash); 131621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block = ext2fs_le32_to_cpu(ent[i].block); 1328deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato fprintf(pager, "Entry #%d: Hash 0x%08x, block %u\n", i, 133621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o i ? e.hash : 0, e.block); 134df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (level) 1353e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_block(fs, ino, inode, rootnode, 136621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block, buf, level-1); 137df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o else 1383e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_leaf_node(fs, ino, inode, rootnode, 139621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block, buf); 140df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 141df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 142df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "---------------------\n"); 143df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 144df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 145df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 146df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 1473e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 148df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t blk, char *buf, int level) 149df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 150df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *cbuf; 151df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 152df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t pblk; 153df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 154df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o cbuf = malloc(fs->blocksize); 155df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!cbuf) { 156df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Couldn't allocate child block.\n"); 157df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 158df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 159df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 160df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 161df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 162df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_int_block", errcode, 1638deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato "while mapping logical block %u\n", blk); 164df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 165df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 166df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 167df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, pblk, 1, buf); 168df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 169df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_int_block", errcode, 1708deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato "while reading block %u\n", blk); 171df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 172df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 173df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 1743e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_node(fs, ino, inode, rootnode, 175503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o (struct ext2_dx_entry *) (buf+8), 176df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o cbuf, level); 177df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(cbuf); 178df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 179df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 180df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 181df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 182df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_htree_dump(int argc, char *argv[]) 183df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 184df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2_ino_t ino; 185df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode inode; 1863e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o int c; 187df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int long_opt; 1883e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o char *buf = NULL; 1893e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info *rootnode; 190df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_entry *ent; 191df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_countlimit *limit; 192df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 193df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 194df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (check_fs_open(argv[0])) 195df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 196df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 197df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pager = open_pager(); 198df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 19988494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o reset_getopt(); 200df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while ((c = getopt (argc, argv, "l")) != EOF) { 201df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o switch (c) { 202df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o case 'l': 203df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o long_opt++; 204df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o break; 20549c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o default: 20649c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o goto print_usage; 207df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 208df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 209df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 210df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc > optind+1) { 21149c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o print_usage: 212df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(0, 0, "Usage: htree_dump [-l] file"); 213155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 214df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 215df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 216df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc == optind) 217df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ino = cwd; 218df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o else 219df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ino = string_to_inode(argv[optind]); 220df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!ino) 221155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 222df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 223df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (debugfs_read_inode(ino, &inode, argv[1])) 224155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 225df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 226df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!LINUX_S_ISDIR(inode.i_mode)) { 227df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Not a directory"); 228155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 229df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 230df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 231df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if ((inode.i_flags & EXT2_BTREE_FL) == 0) { 232df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Not a hash-indexed directory"); 233155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 234df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 235df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 236df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o buf = malloc(2*current_fs->blocksize); 237df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!buf) { 238df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Couldn't allocate htree buffer"); 239155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 240df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 241df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 242df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, inode.i_block[0], 243df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 1, buf); 244df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 245df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], errcode, "Error reading root node"); 246df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o goto errout; 247df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 248df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2493e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o rootnode = (struct ext2_dx_root_info *) (buf + 24); 250df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 251df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Root node dump:\n"); 2528deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); 2533e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); 2543e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Info length: %d\n", rootnode->info_length); 2553e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); 2563e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); 257df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2583e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); 259df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o limit = (struct ext2_dx_countlimit *) ent; 260df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2613e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, 262df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o buf + current_fs->blocksize, 2633e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o rootnode->indirect_levels); 264df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 265df614db6ef79c767745b8154c26d69398b571605Theodore Ts'oerrout: 266df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (buf) 267df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(buf); 268df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o close_pager(pager); 269df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 270df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 271df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 272df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * This function prints the hash of a given file. 273df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 274df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_dx_hash(int argc, char *argv[]) 275df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 276503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o ext2_dirhash_t hash, minor_hash; 27752783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o errcode_t err; 278503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o int c; 279503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o int hash_version = 0; 280503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o __u32 hash_seed[4]; 28152783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o 282503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0; 28388494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o 28488494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o reset_getopt(); 285503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o while ((c = getopt (argc, argv, "h:")) != EOF) { 286503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o switch (c) { 287503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o case 'h': 288503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_version = atoi(optarg); 289503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o break; 29049c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o default: 29149c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o goto print_usage; 292503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o } 293503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o } 294503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o if (optind != argc-1) { 29549c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o print_usage: 296df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "usage: dx_hash filename"); 297df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 298df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 299503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]), 300503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_seed, &hash, &minor_hash); 30152783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o if (err) { 30252783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o com_err(argv[0], err, "while caclulating hash"); 30352783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o return; 30452783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o } 305503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind], 306503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash, minor_hash); 307df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 308df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 309df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 310df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * Search for particular directory entry (useful for debugging very 311df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * large hash tree directories that have lost some blocks from the 312df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * btree index). 313df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 314df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostruct process_block_struct { 315df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *search_name; 316df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *buf; 317df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int len; 318df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o}; 319df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 320df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 321df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o e2_blkcnt_t blockcnt, blk_t ref_blk, 322df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int ref_offset, void *priv_data); 323df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 324df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_dirsearch(int argc, char *argv[]) 325df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 326df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2_ino_t inode; 327df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct process_block_struct pb; 328df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 329df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (check_fs_open(argv[0])) 330df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 331df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 332df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc != 3) { 333df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(0, 0, "Usage: dirsearch dir filename"); 334df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 335df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 336df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 337df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o inode = string_to_inode(argv[1]); 338df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!inode) 339df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 340df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 341df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.buf = malloc(current_fs->blocksize); 342df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!pb.buf) { 343df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("dirsearch", 0, "Couldn't allocate buffer"); 344df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 345df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 346df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.search_name = argv[2]; 347df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.len = strlen(pb.search_name); 348df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 349df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2fs_block_iterate2(current_fs, inode, 0, 0, search_dir_block, &pb); 350df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 351df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(pb.buf); 352df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 353df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 354df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 355df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 356544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt, 357544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o blk_t ref_blk EXT2FS_ATTR((unused)), 358544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 359544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o void *priv_data) 360df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 361df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct process_block_struct *p; 362df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dir_entry *dirent; 363df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 364544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 365df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 366df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (blockcnt < 0) 367df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return 0; 368df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 369df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p = (struct process_block_struct *) priv_data; 370df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 371df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, *blocknr, 1, p->buf); 372df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 373df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("search_dir_block", errcode, 374544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o "while reading block %lu", (unsigned long) *blocknr); 375df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return BLOCK_ABORT; 376df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 377df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 378df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while (offset < fs->blocksize) { 379df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o dirent = (struct ext2_dir_entry *) (p->buf + offset); 380df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 381df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (dirent->inode && 382df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p->len == (dirent->name_len & 0xFF) && 383df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o strncmp(p->search_name, dirent->name, 384df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p->len) == 0) { 385df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o printf("Entry found at logical block %lld, " 3868deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato "phys %u, offset %u\n", blockcnt, 387df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o *blocknr, offset); 3888deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("offset %u\n", offset); 389df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return BLOCK_ABORT; 390df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 391df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o offset += dirent->rec_len; 392df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 393df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return 0; 394df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 395df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 396