13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * icheck.c --- given a list of blocks, generate a list of inodes 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * under the terms of the GNU Public License. 63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 73839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 83839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 93839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <ctype.h> 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 1450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_ERRNO_H 1550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 1650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "debugfs.h" 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct block_info { 22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk; 23b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t ino; 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct block_walk_struct { 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct block_info *barray; 2889e25cfdbf206d6840dc92385ee839dd850294dbAndreas Dilger e2_blkcnt_t blocks_left; 2989e25cfdbf206d6840dc92385ee839dd850294dbAndreas Dilger e2_blkcnt_t num_blocks; 30b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t inode; 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 33544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic int icheck_proc(ext2_filsys fs EXT2FS_ATTR((unused)), 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t *block_nr, 35544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t ref_block EXT2FS_ATTR((unused)), 37544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 3850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o void *private) 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct block_walk_struct *bw = (struct block_walk_struct *) private; 4189e25cfdbf206d6840dc92385ee839dd850294dbAndreas Dilger e2_blkcnt_t i; 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o for (i=0; i < bw->num_blocks; i++) { 44ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o if (!bw->barray[i].ino && bw->barray[i].blk == *block_nr) { 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o bw->barray[i].ino = bw->inode; 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o bw->blocks_left--; 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!bw->blocks_left) 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 51efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ovoid do_icheck(int argc, char **argv) 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct block_walk_struct bw; 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct block_info *binfo; 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2_inode_scan scan = 0; 61b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t ino; 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *block_buf; 65efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc < 2) { 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err(argv[0], 0, "Usage: icheck <block number> ..."); 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (check_fs_open(argv[0])) 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o bw.barray = malloc(sizeof(struct block_info) * argc); 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!bw.barray) { 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("icheck", ENOMEM, 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while allocating inode info array"); 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(bw.barray, 0, sizeof(struct block_info) * argc); 803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 81fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o block_buf = malloc(current_fs->blocksize * 3); 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!block_buf) { 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("icheck", ENOMEM, "while allocating block buffer"); 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o for (i=1; i < argc; i++) { 88e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if (strtoblk(argv[0], argv[i], &bw.barray[i-1].blk)) 892f1ecfa5f8ca0e03fc7684962443829b7f20c7d1Brian Behlendorf goto error_out; 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o bw.num_blocks = bw.blocks_left = argc-1; 933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 94fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o retval = ext2fs_open_inode_scan(current_fs, 0, &scan); 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("icheck", retval, "while opening inode scan"); 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 100643efb8a791e8b16b649643b41e02fab96d28df8Theodore Ts'o do { 101643efb8a791e8b16b649643b41e02fab96d28df8Theodore Ts'o retval = ext2fs_get_next_inode(scan, &ino, &inode); 102643efb8a791e8b16b649643b41e02fab96d28df8Theodore Ts'o } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("icheck", retval, "while starting inode scan"); 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 107efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o while (ino) { 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk; 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!inode.i_links_count) 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 113ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o 1146a2efe047d19d86d1a78f7fc4ff1bf256437c267Theodore Ts'o bw.inode = ino; 1156a2efe047d19d86d1a78f7fc4ff1bf256437c267Theodore Ts'o 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_file_acl_block(current_fs, &inode); 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk) { 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall icheck_proc(current_fs, &blk, 0, 1190ccd488a764c14b27983b92435deca5e1adf9061Theodore Ts'o 0, 0, &bw); 120ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o if (bw.blocks_left == 0) 121ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o break; 122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_acl_block_set(current_fs, &inode, blk); 123ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o } 124ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!ext2fs_inode_has_valid_blocks2(current_fs, &inode)) 126ce5ee99548593426b477a554653439ff7b11faceTheodore Ts'o goto next; 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * To handle filesystems touched by 0.3c extfs; can be 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * removed later. 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (inode.i_dtime) 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_block_iterate3(current_fs, ino, 13543323be95742298b8229be728c3812e95c90629cTheodore Ts'o BLOCK_FLAG_READ_ONLY, block_buf, 13689e25cfdbf206d6840dc92385ee839dd850294dbAndreas Dilger icheck_proc, &bw); 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("icheck", retval, 13989e25cfdbf206d6840dc92385ee839dd850294dbAndreas Dilger "while calling ext2fs_block_iterate"); 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (bw.blocks_left == 0) 1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o next: 147643efb8a791e8b16b649643b41e02fab96d28df8Theodore Ts'o do { 148643efb8a791e8b16b649643b41e02fab96d28df8Theodore Ts'o retval = ext2fs_get_next_inode(scan, &ino, &inode); 149643efb8a791e8b16b649643b41e02fab96d28df8Theodore Ts'o } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); 1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err("icheck", retval, 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "while doing inode scan"); 1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o printf("Block\tInode number\n"); 1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o for (i=0, binfo = bw.barray; i < bw.num_blocks; i++, binfo++) { 1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (binfo->ino == 0) { 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%llu\t<block not found>\n", binfo->blk); 1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%llu\t%u\n", binfo->blk, binfo->ino); 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(bw.barray); 16845e338f5332a54295893dba2e32cc093d1316f60Jim Meyering free(block_buf); 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (scan) 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_close_inode_scan(scan); 1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 173