/*
 * badblocks.c --- replace/append bad blocks to the bad block inode
 * 
 * Copyright (C) 1993, 1994 Theodore Ts'o.  This file may be
 * redistributed under the terms of the GNU Public License.
 */

#include <time.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif

#include <et/com_err.h>
#include "e2fsck.h"

static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
				 void *priv_data);


static void invalid_block(ext2_filsys fs, blk_t blk)
{
	printf(_("Bad block %u out of range; ignored.\n"), blk);
	return;
}

void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
			  int replace_bad_blocks)
{
	ext2_filsys fs = ctx->fs;
	errcode_t	retval;
	badblocks_list	bb_list = 0;
	FILE		*f;
	char		buf[1024];

	e2fsck_read_bitmaps(ctx);

	/*
	 * Make sure the bad block inode is sane.  If there are any
	 * illegal blocks, clear them.
	 */
	retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0,
				      check_bb_inode_blocks, 0);
	if (retval) {
		com_err("ext2fs_block_iterate", retval,
			_("while sanity checking the bad blocks inode"));
		goto fatal;
	}
	
	/*
	 * If we're appending to the bad blocks inode, read in the
	 * current bad blocks.
	 */
	if (!replace_bad_blocks) {
		retval = ext2fs_read_bb_inode(fs, &bb_list);
		if (retval) {
			com_err("ext2fs_read_bb_inode", retval,
				_("while reading the bad blocks inode"));
			goto fatal;
		}
	}
	
	/*
	 * Now read in the bad blocks from the file; if
	 * bad_blocks_file is null, then try to run the badblocks
	 * command.
	 */
	if (bad_blocks_file) {
		f = fopen(bad_blocks_file, "r");
		if (!f) {
			com_err("read_bad_blocks_file", errno,
				_("while trying to open %s"), bad_blocks_file);
			goto fatal;
		}
	} else {
		sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
			(ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
			(ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "",
			fs->device_name, fs->super->s_blocks_count);
		f = popen(buf, "r");
		if (!f) {
			com_err("read_bad_blocks_file", errno,
				_("while trying popen '%s'"), buf);
			goto fatal;
		}
	}
	retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
	if (bad_blocks_file) 
		fclose(f);
	else
		pclose(f);
	if (retval) {
		com_err("ext2fs_read_bb_FILE", retval,
			_("while reading in list of bad blocks from file"));
		goto fatal;
	}
	
	/*
	 * Finally, update the bad blocks from the bad_block_map
	 */
	retval = ext2fs_update_bb_inode(fs, bb_list);
	if (retval) {
		com_err("ext2fs_update_bb_inode", retval,
			_("while updating bad block inode"));
		goto fatal;
	}

	ext2fs_badblocks_list_free(bb_list);
	return;
	
fatal:
	ctx->flags |= E2F_FLAG_ABORT;
	return;
	
}

void test_disk(e2fsck_t ctx)
{
	read_bad_blocks_file(ctx, 0, 0);
}

static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
				 void *priv_data)
{
	if (!*block_nr)
		return 0;

	/*
	 * If the block number is outrageous, clear it and ignore it.
	 */
	if (*block_nr >= fs->super->s_blocks_count ||
	    *block_nr < fs->super->s_first_data_block) {
		printf(_("Warning illegal block %u found in bad block inode.  Cleared.\n"), *block_nr);
		*block_nr = 0;
		return BLOCK_CHANGED;
	}

	return 0;
}

