/*
 * 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 EXT2FS_ATTR((unused)), 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, "%s",
			_("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, "%s",
				_("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 -X %s%s%s %llu", fs->blocksize,
			(ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
			(ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "",
			fs->device_name, ext2fs_blocks_count(fs->super)-1);
		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, "%s",
			_("while reading in list of bad blocks from file"));
		goto fatal;
	}

	/*
	 * Finally, update the bad blocks from the bad_block_map
	 */
	printf("%s: Updating bad block inode.\n", ctx->device_name);
	retval = ext2fs_update_bb_inode(fs, bb_list);
	if (retval) {
		com_err("ext2fs_update_bb_inode", retval, "%s",
			_("while updating bad block inode"));
		goto fatal;
	}

	ext2fs_badblocks_list_free(bb_list);
	return;

fatal:
	ctx->flags |= E2F_FLAG_ABORT;
	return;

}

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

	/*
	 * If the block number is outrageous, clear it and ignore it.
	 */
	if (*block_nr >= ext2fs_blocks_count(fs->super) ||
	    *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;
}

