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" 2642080a8656895eddb0e054c3af86667a5a6aff9fTheodore Ts'o#include "uuid/uuid.h" 2742080a8656895eddb0e054c3af86667a5a6aff9fTheodore Ts'o#include "e2p/e2p.h" 28df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 29df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic FILE *pager; 30df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 31df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, 32df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 333e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, char *buf) 35df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 36df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 37df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dir_entry *dirent; 38544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int thislen, col = 0; 39544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 40b772900b4bcff407c883b7bd8419af56be0a9823Brian Behlendorf char name[EXT2_NAME_LEN + 1]; 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char tmp[EXT2_NAME_LEN + 64]; 42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t pblk; 43226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o ext2_dirhash_t hash, minor_hash; 448a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len; 458a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o int hash_alg; 46efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode = ext2fs_bmap2(fs, ino, inode, buf, 0, blk, 0, &pblk); 48df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 49df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "while mapping logical block %llu\n", blk); 51df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 52df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 53df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(pager, "Reading directory block %llu, phys %llu\n", blk, pblk); 558132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0); 56df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 57df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "while reading block %llu (%llu)\n", 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk, pblk); 60df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 61df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 62f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o hash_alg = rootnode->hash_version; 63f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o if ((hash_alg <= EXT2_HASH_TEA) && 64f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 65f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o hash_alg += 3; 66df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 67df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while (offset < fs->blocksize) { 68df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o dirent = (struct ext2_dir_entry *) (buf + offset); 698a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o errcode = ext2fs_get_rec_len(fs, dirent, &rec_len); 708a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if (errcode) { 718a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o com_err("htree_dump_leaf_inode", errcode, 728a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o "while getting rec_len for block %lu", 738a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (unsigned long) blk); 748a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o return; 758a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o } 765dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (((offset + rec_len) > fs->blocksize) || 775dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (rec_len < 8) || 785dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o ((rec_len % 4) != 0) || 7942080a8656895eddb0e054c3af86667a5a6aff9fTheodore Ts'o ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) { 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(pager, "Corrupted directory block (%llu)!\n", 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk); 82df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o break; 83df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall thislen = dirent->name_len & 0xFF; 85df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o strncpy(name, dirent->name, thislen); 86df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o name[thislen] = '\0'; 87f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o errcode = ext2fs_dirhash(hash_alg, name, 883e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o thislen, fs->super->s_hash_seed, 89226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o &hash, &minor_hash); 9052783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o if (errcode) 9152783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 9252783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o "while calculating hash"); 93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall snprintf(tmp, EXT2_NAME_LEN + 64, "%u 0x%08x-%08x (%d) %s ", 94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dirent->inode, hash, minor_hash, rec_len, name); 95df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o thislen = strlen(tmp); 96df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (col + thislen > 80) { 97df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 98df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o col = 0; 99df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 100df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "%s", tmp); 101df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o col += thislen; 1025dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o offset += rec_len; 103df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 104df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 105df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 106df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 107df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 108df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 109df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 1103e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, char *buf, int level); 112df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 113df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 114df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, 115df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 1163e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 117efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o struct ext2_dx_entry *ent, 118df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *buf, int level) 119df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 120621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o struct ext2_dx_countlimit limit; 121621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o struct ext2_dx_entry e; 12242e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o int hash, i; 123efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 124df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 125621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit = *((struct ext2_dx_countlimit *) ent); 126621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit.count = ext2fs_le16_to_cpu(limit.count); 127621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit.limit = ext2fs_le16_to_cpu(limit.limit); 128df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 129621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o fprintf(pager, "Number of entries (count): %d\n", limit.count); 130621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o fprintf(pager, "Number of entries (limit): %d\n", limit.limit); 131df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 13242e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o for (i=0; i < limit.count; i++) { 13342e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o hash = i ? ext2fs_le32_to_cpu(ent[i].hash) : 0; 134d0ff90d5202428583c78a60c3042e7b60d88bc45Eric Sandeen fprintf(pager, "Entry #%d: Hash 0x%08x%s, block %u\n", i, 13542e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o hash, (hash & 1) ? " (**)" : "", 136621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o ext2fs_le32_to_cpu(ent[i].block)); 13742e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o } 138df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 139df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 140df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 141621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o for (i=0; i < limit.count; i++) { 142621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.hash = ext2fs_le32_to_cpu(ent[i].hash); 143621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block = ext2fs_le32_to_cpu(ent[i].block); 1448deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato fprintf(pager, "Entry #%d: Hash 0x%08x, block %u\n", i, 145621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o i ? e.hash : 0, e.block); 146df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (level) 1473e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_block(fs, ino, inode, rootnode, 148621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block, buf, level-1); 149df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o else 1503e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_leaf_node(fs, ino, inode, rootnode, 151621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block, buf); 152df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 153df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 154df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "---------------------\n"); 155df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 156df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 157df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 158df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 1593e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info * rootnode, 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, char *buf, int level) 161df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 162df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *cbuf; 163df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t pblk; 165df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 166df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o cbuf = malloc(fs->blocksize); 167df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!cbuf) { 168df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Couldn't allocate child block.\n"); 169df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 170df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 171efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode = ext2fs_bmap2(fs, ino, inode, buf, 0, blk, 0, &pblk); 173df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 174df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_int_block", errcode, 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "while mapping logical block %llu\n", blk); 17689456558df36b22ca664ead88e768d6a486c7cefBrian Behlendorf goto errout; 177df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 178df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode = io_channel_read_blk64(current_fs->io, pblk, 1, buf); 180df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 181df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_int_block", errcode, 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "while reading block %llu\n", blk); 18389456558df36b22ca664ead88e768d6a486c7cefBrian Behlendorf goto errout; 184df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 185df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 1863e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_node(fs, ino, inode, rootnode, 187503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o (struct ext2_dx_entry *) (buf+8), 188df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o cbuf, level); 18989456558df36b22ca664ead88e768d6a486c7cefBrian Behlendorferrout: 190df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(cbuf); 191df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 192df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 193df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 194df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 195df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_htree_dump(int argc, char *argv[]) 196df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 197df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2_ino_t ino; 198df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode inode; 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk; 2003e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o char *buf = NULL; 2013e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o struct ext2_dx_root_info *rootnode; 202df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_entry *ent; 203df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 204df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 205df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (check_fs_open(argv[0])) 206df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 207df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 208df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pager = open_pager(); 209df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (common_inode_args_process(argc, argv, &ino, 0)) 211155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 212df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 213df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (debugfs_read_inode(ino, &inode, argv[1])) 214155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 215df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 216df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!LINUX_S_ISDIR(inode.i_mode)) { 217df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Not a directory"); 218155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 219df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 220efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 221df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if ((inode.i_flags & EXT2_BTREE_FL) == 0) { 222df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Not a hash-indexed directory"); 223155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 224df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 225df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 226df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o buf = malloc(2*current_fs->blocksize); 227df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!buf) { 228df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Couldn't allocate htree buffer"); 229155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 230df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 231df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode = ext2fs_bmap2(current_fs, ino, &inode, buf, 0, 0, 0, &blk); 233226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o if (errcode) { 234226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o com_err("do_htree_block", errcode, 235226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o "while mapping logical block 0\n"); 236226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o goto errout; 237226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o } 238226515dfa921dfaa0145f358d0e457852dc3b493Theodore Ts'o 239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode = io_channel_read_blk64(current_fs->io, blk, 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1, buf); 241df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 242df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], errcode, "Error reading root node"); 243df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o goto errout; 244df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 245df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2463e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o rootnode = (struct ext2_dx_root_info *) (buf + 24); 247df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 248df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Root node dump:\n"); 2498deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); 2503e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); 2513e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Info length: %d\n", rootnode->info_length); 2523e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); 2533e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); 254df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2553e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); 256df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 2573e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, 258df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o buf + current_fs->blocksize, 2593e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'o rootnode->indirect_levels); 260df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 261df614db6ef79c767745b8154c26d69398b571605Theodore Ts'oerrout: 26245e338f5332a54295893dba2e32cc093d1316f60Jim Meyering free(buf); 263df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o close_pager(pager); 264df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 265df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 266df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 267df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * This function prints the hash of a given file. 268df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 269df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_dx_hash(int argc, char *argv[]) 270df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 271503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o ext2_dirhash_t hash, minor_hash; 27252783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o errcode_t err; 273503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o int c; 274503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o int hash_version = 0; 275503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o __u32 hash_seed[4]; 276efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 277503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0; 27888494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o 27988494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o reset_getopt(); 280f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o while ((c = getopt (argc, argv, "h:s:")) != EOF) { 281503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o switch (c) { 282503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o case 'h': 283f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o hash_version = e2p_string2hash(optarg); 284f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o if (hash_version < 0) 285f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o hash_version = atoi(optarg); 286f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o break; 287f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o case 's': 28842080a8656895eddb0e054c3af86667a5a6aff9fTheodore Ts'o if (uuid_parse(optarg, (unsigned char *) hash_seed)) { 289f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o fprintf(stderr, "Invalid UUID format: %s\n", 290f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o optarg); 291f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o return; 292f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o } 293503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o break; 29449c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o default: 29549c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o goto print_usage; 296503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o } 297503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o } 298503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o if (optind != argc-1) { 29949c6b4e9472f53c252126f1c9a5a6e9629967d1fTheodore Ts'o print_usage: 300f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o com_err(argv[0], 0, "usage: dx_hash [-h hash_alg] " 301f8bd55160cde8a678a9ddbf69b7555504b253befTheodore Ts'o "[-s hash_seed] filename"); 302df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 303df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 304503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]), 305503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_seed, &hash, &minor_hash); 30652783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o if (err) { 30752783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o com_err(argv[0], err, "while caclulating hash"); 30852783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o return; 30952783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o } 310503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind], 311503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash, minor_hash); 312df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 313df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 314df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 315df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * Search for particular directory entry (useful for debugging very 316df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * large hash tree directories that have lost some blocks from the 317df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * btree index). 318df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 319df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostruct process_block_struct { 320df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *search_name; 321df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *buf; 322df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int len; 323df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o}; 324df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int search_dir_block(ext2_filsys fs, blk64_t *blocknr, 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall e2_blkcnt_t blockcnt, blk64_t ref_blk, 327df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int ref_offset, void *priv_data); 328df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 329df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_dirsearch(int argc, char *argv[]) 330df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 331df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2_ino_t inode; 332df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct process_block_struct pb; 333efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 334df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (check_fs_open(argv[0])) 335df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 336df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 337df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc != 3) { 338df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(0, 0, "Usage: dirsearch dir filename"); 339df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 340df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 341df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 342df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o inode = string_to_inode(argv[1]); 343df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!inode) 344df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 345df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 346df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.buf = malloc(current_fs->blocksize); 347df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!pb.buf) { 348df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("dirsearch", 0, "Couldn't allocate buffer"); 349df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 350df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 351df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.search_name = argv[2]; 352df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.len = strlen(pb.search_name); 353efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, 0, 35543323be95742298b8229be728c3812e95c90629cTheodore Ts'o search_dir_block, &pb); 356df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 357df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(pb.buf); 358df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 359df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 360df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int search_dir_block(ext2_filsys fs, blk64_t *blocknr, 362efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e2_blkcnt_t blockcnt, 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t ref_blk EXT2FS_ATTR((unused)), 364544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 365544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o void *priv_data) 366df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 367df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct process_block_struct *p; 368df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dir_entry *dirent; 369df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 370544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 3718a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len; 372df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 373df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (blockcnt < 0) 374df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return 0; 375df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 376df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p = (struct process_block_struct *) priv_data; 377df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode = io_channel_read_blk64(current_fs->io, *blocknr, 1, p->buf); 379df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 380df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("search_dir_block", errcode, 381544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o "while reading block %lu", (unsigned long) *blocknr); 382df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return BLOCK_ABORT; 383df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 384df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 385df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while (offset < fs->blocksize) { 386df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o dirent = (struct ext2_dir_entry *) (p->buf + offset); 3878a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o errcode = ext2fs_get_rec_len(fs, dirent, &rec_len); 3888a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o if (errcode) { 3898a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o com_err("htree_dump_leaf_inode", errcode, 3908a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o "while getting rec_len for block %lu", 3918a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (unsigned long) *blocknr); 39242080a8656895eddb0e054c3af86667a5a6aff9fTheodore Ts'o return BLOCK_ABORT; 3938a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o } 394df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (dirent->inode && 395efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o p->len == (dirent->name_len & 0xFF) && 396df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o strncmp(p->search_name, dirent->name, 397df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p->len) == 0) { 398df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o printf("Entry found at logical block %lld, " 399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "phys %llu, offset %u\n", (long long)blockcnt, 400df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o *blocknr, offset); 4018deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("offset %u\n", offset); 402df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return BLOCK_ABORT; 403df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 4045dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o offset += rec_len; 405df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 406df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return 0; 407df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 408df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 409