htree.c revision 42e5b5f987ce869cb50e765bb985dddc5d70d753
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#ifdef HAVE_OPTRESET 25df614db6ef79c767745b8154c26d69398b571605Theodore Ts'oextern int optreset; /* defined by BSD, but not others */ 26df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#endif 27df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 28df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#include "debugfs.h" 29df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 30df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic FILE *pager; 31df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 32df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, 33df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 34503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o struct ext2_dx_root_info * root, 35df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t blk, char *buf) 36df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 37df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 38df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dir_entry *dirent; 39df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int thislen, col = 0, offset = 0; 40df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char name[EXT2_NAME_LEN]; 41df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char tmp[EXT2_NAME_LEN + 16]; 42df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t pblk; 4352783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o ext2_dirhash_t hash; 44df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 45df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 46df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 47df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 48df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o "while mapping logical block %d\n", blk); 49df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 50df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 51df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 52df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, pblk, 1, buf); 53df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 54df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 55df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o "while reading block %d\n", blk); 56df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 57df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 58df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 59df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while (offset < fs->blocksize) { 60df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o dirent = (struct ext2_dir_entry *) (buf + offset); 61df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (((offset + dirent->rec_len) > fs->blocksize) || 62df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o (dirent->rec_len < 8) || 63df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ((dirent->rec_len % 4) != 0) || 64df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { 65df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Corrupted directory block (%d)!\n", blk); 66df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o break; 67df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 68df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? 69df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o (dirent->name_len & 0xFF) : EXT2_NAME_LEN; 70df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o strncpy(name, dirent->name, thislen); 71df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o name[thislen] = '\0'; 72503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o errcode = ext2fs_dirhash(root->hash_version, name, thislen, 73503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o fs->super->s_hash_seed, 74503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o &hash, 0); 7552783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o if (errcode) 7652783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o com_err("htree_dump_leaf_node", errcode, 7752783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o "while calculating hash"); 78df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o sprintf(tmp, "%u 0x%08x (%d) %s ", dirent->inode, 7952783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o hash, dirent->rec_len, name); 80df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o thislen = strlen(tmp); 81df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (col + thislen > 80) { 82df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 83df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o col = 0; 84df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 85df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "%s", tmp); 86df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o col += thislen; 87df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o offset += dirent->rec_len; 88df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 89df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 90df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 91df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 92df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 93df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 94df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 95503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o struct ext2_dx_root_info * root, 96df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t blk, char *buf, int level); 97df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 98df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 99df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, 100df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 101503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o struct ext2_dx_root_info * root, 102df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_entry *ent, 103df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *buf, int level) 104df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 105621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o struct ext2_dx_countlimit limit; 106621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o struct ext2_dx_entry e; 10742e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o int hash, i; 108621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o 109df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 110621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit = *((struct ext2_dx_countlimit *) ent); 111621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit.count = ext2fs_le16_to_cpu(limit.count); 112621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o limit.limit = ext2fs_le16_to_cpu(limit.limit); 113df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 114621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o fprintf(pager, "Number of entries (count): %d\n", limit.count); 115621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o fprintf(pager, "Number of entries (limit): %d\n", limit.limit); 116df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 11742e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o for (i=0; i < limit.count; i++) { 11842e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o hash = i ? ext2fs_le32_to_cpu(ent[i].hash) : 0; 11942e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o fprintf(pager, "Entry #%d: Hash 0x%08x%s, block %d\n", i, 12042e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o hash, (hash & 1) ? " (**)" : "", 121621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o ext2fs_le32_to_cpu(ent[i].block)); 12242e5b5f987ce869cb50e765bb985dddc5d70d753Theodore Ts'o } 123df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 124df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\n"); 125df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 126621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o for (i=0; i < limit.count; i++) { 127621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.hash = ext2fs_le32_to_cpu(ent[i].hash); 128621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block = ext2fs_le32_to_cpu(ent[i].block); 129df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Entry #%d: Hash 0x%08x, block %d\n", i, 130621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o i ? e.hash : 0, e.block); 131df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (level) 132503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o htree_dump_int_block(fs, ino, inode, root, 133621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block, buf, level-1); 134df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o else 135503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o htree_dump_leaf_node(fs, ino, inode, root, 136621732c956f8ff049d032354fc8d6eab9abab1f4Theodore Ts'o e.block, buf); 137df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 138df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 139df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "---------------------\n"); 140df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 141df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 142df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, 143df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode *inode, 144503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o struct ext2_dx_root_info * root, 145df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t blk, char *buf, int level) 146df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 147df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *cbuf; 148df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 149df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o blk_t pblk; 150df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 151df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o cbuf = malloc(fs->blocksize); 152df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!cbuf) { 153df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Couldn't allocate child block.\n"); 154df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 155df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 156df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 157df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); 158df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 159df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_int_block", errcode, 160df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o "while mapping logical block %d\n", blk); 161df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 162df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 163df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 164df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, pblk, 1, buf); 165df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 166df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("htree_dump_int_block", errcode, 167df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o "while reading block %d\n", blk); 168df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 169df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 170df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 171503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o htree_dump_int_node(fs, ino, inode, root, 172503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o (struct ext2_dx_entry *) (buf+8), 173df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o cbuf, level); 174df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(cbuf); 175df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 176df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 177df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 178df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 179df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_htree_dump(int argc, char *argv[]) 180df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 181df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2_ino_t ino; 182df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_inode inode; 183df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int retval; 184df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int i, c; 185df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int flags; 186df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int long_opt; 187df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o void *buf = NULL; 188df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_root_info *root; 189df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_entry *ent; 190df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dx_countlimit *limit; 191df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 192df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 193df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (check_fs_open(argv[0])) 194df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 195df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 196df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pager = open_pager(); 197df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 198df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o optind = 0; 199df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#ifdef HAVE_OPTRESET 200df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o optreset = 1; /* Makes BSD getopt happy */ 201df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o#endif 202df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while ((c = getopt (argc, argv, "l")) != EOF) { 203df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o switch (c) { 204df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o case 'l': 205df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o long_opt++; 206df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o break; 207df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 208df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 209df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 210df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc > optind+1) { 211df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(0, 0, "Usage: htree_dump [-l] file"); 212155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 213df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 214df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 215df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc == optind) 216df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ino = cwd; 217df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o else 218df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ino = string_to_inode(argv[optind]); 219df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!ino) 220155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 221df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 222df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (debugfs_read_inode(ino, &inode, argv[1])) 223155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 224df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 225df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!LINUX_S_ISDIR(inode.i_mode)) { 226df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Not a directory"); 227155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 228df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 229df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 230df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if ((inode.i_flags & EXT2_BTREE_FL) == 0) { 231df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Not a hash-indexed directory"); 232155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 233df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 234df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 235df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o buf = malloc(2*current_fs->blocksize); 236df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!buf) { 237df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "Couldn't allocate htree buffer"); 238155f577b2b28a964f70d21634ff173705a76c7c3Theodore Ts'o goto errout; 239df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 240df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 241df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, inode.i_block[0], 242df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 1, buf); 243df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 244df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], errcode, "Error reading root node"); 245df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o goto errout; 246df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 247df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 248df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o root = (struct ext2_dx_root_info *) (buf + 24); 249df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 250df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "Root node dump:\n"); 251df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\t Reserved zero: %d\n", root->reserved_zero); 252df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\t Hash Version: %d\n", root->hash_version); 253df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\t Info length: %d\n", root->info_length); 254df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\t Indirect levels: %d\n", root->indirect_levels); 255df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o fprintf(pager, "\t Flags: %d\n", root->unused_flags); 256df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 257df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ent = (struct ext2_dx_entry *) (buf + 24 + root->info_length); 258df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o limit = (struct ext2_dx_countlimit *) ent; 259df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 260503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o htree_dump_int_node(current_fs, ino, &inode, root, ent, 261df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o buf + current_fs->blocksize, 262df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o root->indirect_levels); 263df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 264df614db6ef79c767745b8154c26d69398b571605Theodore Ts'oerrout: 265df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (buf) 266df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(buf); 267df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o close_pager(pager); 268df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 269df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 270df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 271df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * This function prints the hash of a given file. 272df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 273df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_dx_hash(int argc, char *argv[]) 274df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 275503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o ext2_dirhash_t hash, minor_hash; 27652783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o errcode_t err; 277503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o int c; 278503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o int hash_version = 0; 279503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o __u32 hash_seed[4]; 28052783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o 281503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0; 282503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o optind = 0; 283503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o#ifdef HAVE_OPTRESET 284503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o optreset = 1; /* Makes BSD getopt happy */ 285503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o#endif 286503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o while ((c = getopt (argc, argv, "h:")) != EOF) { 287503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o switch (c) { 288503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o case 'h': 289503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_version = atoi(optarg); 290503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o break; 291503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o } 292503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o } 293503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o if (optind != argc-1) { 294df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(argv[0], 0, "usage: dx_hash filename"); 295df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 296df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 297503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]), 298503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash_seed, &hash, &minor_hash); 29952783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o if (err) { 30052783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o com_err(argv[0], err, "while caclulating hash"); 30152783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o return; 30252783e0ca72a80c549e9d266b3472f78fc61bdb2Theodore Ts'o } 303503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind], 304503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o hash, minor_hash); 305df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 306df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 307df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o/* 308df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * Search for particular directory entry (useful for debugging very 309df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * large hash tree directories that have lost some blocks from the 310df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o * btree index). 311df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o */ 312df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostruct process_block_struct { 313df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *search_name; 314df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o char *buf; 315df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int len; 316df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o}; 317df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 318df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 319df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o e2_blkcnt_t blockcnt, blk_t ref_blk, 320df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int ref_offset, void *priv_data); 321df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 322df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ovoid do_dirsearch(int argc, char *argv[]) 323df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 324df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2_ino_t inode; 325df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int retval; 326df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int c; 327df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int flags; 328df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct process_block_struct pb; 329df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 330df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (check_fs_open(argv[0])) 331df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 332df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 333df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (argc != 3) { 334df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err(0, 0, "Usage: dirsearch dir filename"); 335df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 336df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 337df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 338df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o inode = string_to_inode(argv[1]); 339df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!inode) 340df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 341df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 342df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.buf = malloc(current_fs->blocksize); 343df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (!pb.buf) { 344df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("dirsearch", 0, "Couldn't allocate buffer"); 345df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return; 346df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 347df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.search_name = argv[2]; 348df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o pb.len = strlen(pb.search_name); 349df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 350df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o ext2fs_block_iterate2(current_fs, inode, 0, 0, search_dir_block, &pb); 351df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 352df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o free(pb.buf); 353df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 354df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 355df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 356df614db6ef79c767745b8154c26d69398b571605Theodore Ts'ostatic int search_dir_block(ext2_filsys fs, blk_t *blocknr, 357df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o e2_blkcnt_t blockcnt, blk_t ref_blk, 358df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int ref_offset, void *priv_data) 359df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o{ 360df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct process_block_struct *p; 361df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o struct ext2_dir_entry *dirent; 362df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode_t errcode; 363df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o int offset = 0; 364df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 365df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (blockcnt < 0) 366df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return 0; 367df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 368df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p = (struct process_block_struct *) priv_data; 369df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 370df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o errcode = io_channel_read_blk(current_fs->io, *blocknr, 1, p->buf); 371df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (errcode) { 372df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o com_err("search_dir_block", errcode, 373df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o "while reading block %lu", *blocknr); 374df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return BLOCK_ABORT; 375df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 376df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 377df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o while (offset < fs->blocksize) { 378df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o dirent = (struct ext2_dir_entry *) (p->buf + offset); 379df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 380df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o if (dirent->inode && 381df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p->len == (dirent->name_len & 0xFF) && 382df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o strncmp(p->search_name, dirent->name, 383df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o p->len) == 0) { 384df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o printf("Entry found at logical block %lld, " 385df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o "phys %d, offset %d\n", blockcnt, 386df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o *blocknr, offset); 387df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o printf("offset %d\n", offset); 388df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return BLOCK_ABORT; 389df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 390df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o offset += dirent->rec_len; 391df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o } 392df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o return 0; 393df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o} 394df614db6ef79c767745b8154c26d69398b571605Theodore Ts'o 395