119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * icheck.c --- given a list of blocks, generate a list of inodes
33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1994 Theodore Ts'o.  This file may be redistributed
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * under the terms of the GNU Public License.
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h>
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h>
1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdlib.h>
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <ctype.h>
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <time.h>
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_ERRNO_H
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h>
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h>
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "debugfs.h"
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct block_info {
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t		blk;
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t	ino;
2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct block_walk_struct {
2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct block_info	*barray;
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2_blkcnt_t		blocks_left;
2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2_blkcnt_t		num_blocks;
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t		inode;
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int icheck_proc(ext2_filsys fs EXT2FS_ATTR((unused)),
3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       blk_t	*block_nr,
3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       blk_t ref_block EXT2FS_ATTR((unused)),
3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       int ref_offset EXT2FS_ATTR((unused)),
3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		       void *private)
3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct block_walk_struct *bw = (struct block_walk_struct *) private;
4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2_blkcnt_t	i;
4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (i=0; i < bw->num_blocks; i++) {
4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!bw->barray[i].ino && bw->barray[i].blk == *block_nr) {
4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			bw->barray[i].ino = bw->inode;
4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			bw->blocks_left--;
4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!bw->blocks_left)
5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return BLOCK_ABORT;
513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid do_icheck(int argc, char **argv)
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct block_walk_struct bw;
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct block_info	*binfo;
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			i;
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_inode_scan		scan = 0;
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t		ino;
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode	inode;
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t		retval;
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char			*block_buf;
653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (argc < 2) {
6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err(argv[0], 0, "Usage: icheck <block number> ...");
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (check_fs_open(argv[0]))
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	bw.barray = malloc(sizeof(struct block_info) * argc);
7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!bw.barray) {
7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err("icheck", ENOMEM,
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			"while allocating inode info array");
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	memset(bw.barray, 0, sizeof(struct block_info) * argc);
8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	block_buf = malloc(current_fs->blocksize * 3);
8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!block_buf) {
8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err("icheck", ENOMEM, "while allocating block buffer");
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto error_out;
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (i=1; i < argc; i++) {
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (strtoblk(argv[0], argv[i], &bw.barray[i-1].blk))
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto error_out;
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	bw.num_blocks = bw.blocks_left = argc-1;
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_open_inode_scan(current_fs, 0, &scan);
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval) {
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err("icheck", retval, "while opening inode scan");
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto error_out;
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	do {
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_get_next_inode(scan, &ino, &inode);
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE);
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval) {
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err("icheck", retval, "while starting inode scan");
10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto error_out;
10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
1073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (ino) {
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!inode.i_links_count)
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		bw.inode = ino;
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (inode.i_file_acl) {
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			icheck_proc(current_fs, &inode.i_file_acl, 0,
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				    0, 0, &bw);
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (bw.blocks_left == 0)
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				break;
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!ext2fs_inode_has_valid_blocks(&inode))
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * To handle filesystems touched by 0.3c extfs; can be
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * removed later.
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (inode.i_dtime)
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_block_iterate2(current_fs, ino,
1313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					       BLOCK_FLAG_READ_ONLY, block_buf,
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					       icheck_proc, &bw);
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval) {
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err("icheck", retval,
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				"while calling ext2fs_block_iterate");
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (bw.blocks_left == 0)
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	next:
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		do {
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			retval = ext2fs_get_next_inode(scan, &ino, &inode);
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE);
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval) {
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err("icheck", retval,
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				"while doing inode scan");
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto error_out;
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	printf("Block\tInode number\n");
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (i=0, binfo = bw.barray; i < bw.num_blocks; i++, binfo++) {
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (binfo->ino == 0) {
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			printf("%u\t<block not found>\n", binfo->blk);
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			continue;
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		printf("%u\t%u\n", binfo->blk, binfo->ino);
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterror_out:
16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	free(bw.barray);
1643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	free(block_buf);
16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (scan)
16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_close_inode_scan(scan);
16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return;
16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
169