/*
 * tst_inode.c --- this function tests the inode scan function
 * 
 * Copyright (C) 1996 by Theodore Ts'o.
 * 
 * %Begin-Header%
 * This file may be redistributed under the terms of the GNU Public
 * License.
 * %End-Header%
 */

#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#if HAVE_ERRNO_H
#include <errno.h>
#endif

#include "ext2_fs.h"
#include "ext2fs.h"

blk_t test_vec[] = { 8, 12, 24, 34, 43, 44, 100, 0 };

ext2_filsys	test_fs;
ext2fs_block_bitmap bad_block_map, touched_map;
ext2fs_inode_bitmap bad_inode_map;
badblocks_list	test_badblocks;

int first_no_comma = 1;
int failed = 0;

static void test_read_blk(unsigned long block, int count, errcode_t err)
{
	int	i;

	if (first_no_comma)
		first_no_comma = 0;
	else
		printf(", ");

	if (count > 1)
		printf("%lu-%lu", block, block+count-1);
	else
		printf("%lu", block);

	for (i=0; i < count; i++, block++) {
		if (ext2fs_test_block_bitmap(touched_map, block)) {
			printf("\nDuplicate block?!? --- %lu\n", block);
			failed++;
			first_no_comma = 1;
		}
		ext2fs_mark_block_bitmap(touched_map, block);
	}
}

/*
 * Setup the variables for doing the inode scan test.
 */
static void setup(void)
{
	errcode_t	retval;
	int		i;
	struct ext2_super_block param;

	initialize_ext2_error_table();

	memset(&param, 0, sizeof(param));
	param.s_blocks_count = 12000;


	test_io_cb_read_blk = test_read_blk;
	
	retval = ext2fs_initialize("test fs", 0, &param,
				   test_io_manager, &test_fs);
	if (retval) {
		com_err("setup", retval,
			"While initializing filesystem");
		exit(1);
	}
	retval = ext2fs_allocate_tables(test_fs);
	if (retval) {
		com_err("setup", retval,
			"While allocating tables for test filesystem");
		exit(1);
	}
	retval = ext2fs_allocate_block_bitmap(test_fs, "bad block map",
					      &bad_block_map);
	if (retval) {
		com_err("setup", retval,
			"While allocating bad_block bitmap");
		exit(1);
	}
	retval = ext2fs_allocate_block_bitmap(test_fs, "touched map",
					      &touched_map);
	if (retval) {
		com_err("setup", retval,
			"While allocating touched block bitmap");
		exit(1);
	}
	retval = ext2fs_allocate_inode_bitmap(test_fs, "bad inode map",
					      &bad_inode_map);
	if (retval) {
		com_err("setup", retval,
			"While allocating bad inode bitmap");
		exit(1);
	}
	
	retval = ext2fs_badblocks_list_create(&test_badblocks, 5);
	if (retval) {
		com_err("setup", retval, "while creating badblocks list");
		exit(1);
	}
	for (i=0; test_vec[i]; i++) {
		retval = ext2fs_badblocks_list_add(test_badblocks, test_vec[i]);
		if (retval) {
			com_err("setup", retval,
				"while adding test vector %d", i);
			exit(1);
		}
		ext2fs_mark_block_bitmap(bad_block_map, test_vec[i]);
	}
	test_fs->badblocks = test_badblocks;
}

/*
 * Iterate using inode_scan
 */
static void iterate(void)
{
	struct ext2_inode inode;
	ext2_inode_scan	scan;
	errcode_t	retval;
	ext2_ino_t	ino;

	retval = ext2fs_open_inode_scan(test_fs, 8, &scan);
	if (retval) {
		com_err("iterate", retval, "While opening inode scan");
		exit(1);
	}
	printf("Reading blocks: ");
	retval = ext2fs_get_next_inode(scan, &ino, &inode);
	if (retval) {
		com_err("iterate", retval, "while reading first inode");
		exit(1);
	}
	while (ino) {
		retval = ext2fs_get_next_inode(scan, &ino, &inode);
		if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
			ext2fs_mark_inode_bitmap(bad_inode_map, ino);
			continue;
		}
		if (retval) {
			com_err("iterate", retval,
				"while getting next inode");
			exit(1);
		}
	}
	printf("\n");
	ext2fs_close_inode_scan(scan);
}

/*
 * Verify the touched map
 */
static void check_map(void)
{
	int	i, j, first=1;
	unsigned long	blk;

	for (i=0; test_vec[i]; i++) {
		if (ext2fs_test_block_bitmap(touched_map, test_vec[i])) {
			printf("Bad block was touched --- %u\n", test_vec[i]);
			failed++;
			first_no_comma = 1;
		}
		ext2fs_mark_block_bitmap(touched_map, test_vec[i]);
	}
	for (i = 0; i < test_fs->group_desc_count; i++) {
		for (j=0, blk = test_fs->group_desc[i].bg_inode_table;
		     j < test_fs->inode_blocks_per_group;
		     j++, blk++) {
			if (!ext2fs_test_block_bitmap(touched_map, blk) &&
			    !ext2fs_test_block_bitmap(bad_block_map, blk)) {
				printf("Missing block --- %lu\n", blk);
				failed++;
			}
		}
	}
	printf("Bad inodes: ");
	for (i=1; i <= test_fs->super->s_inodes_count; i++) {
		if (ext2fs_test_inode_bitmap(bad_inode_map, i)) {
			if (first)
				first = 0;
			else
				printf(", ");
			printf("%u", i);
		}
	}
	printf("\n");
}


int main(int argc, char **argv)
{
	setup();
	iterate();
	check_map();
	if (!failed)
		printf("Inode scan tested OK!\n");
	return failed;
}

