diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:49:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:49:25 +0000 |
commit | 464df1d5e5ab1322e2dd0a7796939fff1aeefa9a (patch) | |
tree | 6a403684e0978f0287d7f0ec0e5aab1fd31a59e1 /debugfs/icheck.c | |
parent | Initial commit. (diff) | |
download | e2fsprogs-upstream/1.47.0.tar.xz e2fsprogs-upstream/1.47.0.zip |
Adding upstream version 1.47.0.upstream/1.47.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debugfs/icheck.c')
-rw-r--r-- | debugfs/icheck.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/debugfs/icheck.c b/debugfs/icheck.c new file mode 100644 index 0000000..ed6e950 --- /dev/null +++ b/debugfs/icheck.c @@ -0,0 +1,176 @@ +/* + * icheck.c --- given a list of blocks, generate a list of inodes + * + * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> + +#include "debugfs.h" + +struct block_info { + blk64_t blk; + ext2_ino_t ino; +}; + +struct block_walk_struct { + struct block_info *barray; + e2_blkcnt_t blocks_left; + e2_blkcnt_t num_blocks; + ext2_ino_t inode; +}; + +static int icheck_proc(ext2_filsys fs EXT2FS_ATTR((unused)), + blk64_t *block_nr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private) +{ + struct block_walk_struct *bw = (struct block_walk_struct *) private; + e2_blkcnt_t i; + + for (i=0; i < bw->num_blocks; i++) { + if (!bw->barray[i].ino && bw->barray[i].blk == *block_nr) { + bw->barray[i].ino = bw->inode; + bw->blocks_left--; + } + } + if (!bw->blocks_left) + return BLOCK_ABORT; + + return 0; +} + +void do_icheck(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + struct block_walk_struct bw; + struct block_info *binfo; + int i; + ext2_inode_scan scan = 0; + ext2_ino_t ino; + struct ext2_inode inode; + errcode_t retval; + char *block_buf; + + if (argc < 2) { + com_err(argv[0], 0, "Usage: icheck <block number> ..."); + return; + } + if (check_fs_open(argv[0])) + return; + + bw.barray = malloc(sizeof(struct block_info) * argc); + if (!bw.barray) { + com_err("icheck", ENOMEM, + "while allocating inode info array"); + return; + } + memset(bw.barray, 0, sizeof(struct block_info) * argc); + + block_buf = malloc(current_fs->blocksize * 3); + if (!block_buf) { + com_err("icheck", ENOMEM, "while allocating block buffer"); + goto error_out; + } + + for (i=1; i < argc; i++) { + if (strtoblk(argv[0], argv[i], NULL, &bw.barray[i-1].blk)) + goto error_out; + } + + bw.num_blocks = bw.blocks_left = argc-1; + + retval = ext2fs_open_inode_scan(current_fs, 0, &scan); + if (retval) { + com_err("icheck", retval, "while opening inode scan"); + goto error_out; + } + + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); + if (retval) { + com_err("icheck", retval, "while starting inode scan"); + goto error_out; + } + + while (ino) { + blk64_t blk; + + if (!inode.i_links_count) + goto next; + + bw.inode = ino; + + blk = ext2fs_file_acl_block(current_fs, &inode); + if (blk) { + icheck_proc(current_fs, &blk, 0, + 0, 0, &bw); + if (bw.blocks_left == 0) + break; + ext2fs_file_acl_block_set(current_fs, &inode, blk); + } + + if (!ext2fs_inode_has_valid_blocks2(current_fs, &inode)) + goto next; + /* + * To handle filesystems touched by 0.3c extfs; can be + * removed later. + */ + if (inode.i_dtime) + goto next; + + retval = ext2fs_block_iterate3(current_fs, ino, + BLOCK_FLAG_READ_ONLY, block_buf, + icheck_proc, &bw); + if (retval) { + com_err("icheck", retval, + "while calling ext2fs_block_iterate"); + goto next; + } + + if (bw.blocks_left == 0) + break; + + next: + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); + if (retval) { + com_err("icheck", retval, + "while doing inode scan"); + goto error_out; + } + } + + printf("Block\tInode number\n"); + for (i=0, binfo = bw.barray; i < bw.num_blocks; i++, binfo++) { + if (binfo->ino == 0) { + printf("%llu\t<block not found>\n", + (unsigned long long) binfo->blk); + continue; + } + printf("%llu\t%u\n", (unsigned long long) binfo->blk, + binfo->ino); + } + +error_out: + free(bw.barray); + free(block_buf); + if (scan) + ext2fs_close_inode_scan(scan); + return; +} |