/* * ehandler.c --- handle bad block errors which come up during the * course of an e2fsck session. * * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed * under the terms of the GNU Public License. */ #include <stdlib.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include <termios.h> #include "e2fsck.h" #include <sys/time.h> #include <sys/resource.h> static const char *operation; static errcode_t e2fsck_handle_read_error(io_channel channel, unsigned long block, int count, void *data, size_t size EXT2FS_ATTR((unused)), int actual EXT2FS_ATTR((unused)), errcode_t error) { int i; char *p; ext2_filsys fs = (ext2_filsys) channel->app_data; e2fsck_t ctx; ctx = (e2fsck_t) fs->priv_data; if (ctx->flags & E2F_FLAG_EXITING) return 0; /* * If more than one block was read, try reading each block * separately. We could use the actual bytes read to figure * out where to start, but we don't bother. */ if (count > 1) { p = (char *) data; for (i=0; i < count; i++, p += channel->block_size, block++) { error = io_channel_read_blk(channel, block, 1, p); if (error) return error; } return 0; } if (operation) printf(_("Error reading block %lu (%s) while %s. "), block, error_message(error), operation); else printf(_("Error reading block %lu (%s). "), block, error_message(error)); preenhalt(ctx); if (ask(ctx, _("Ignore error"), 1)) { if (ask(ctx, _("Force rewrite"), 1)) io_channel_write_blk(channel, block, 1, data); return 0; } return error; } static errcode_t e2fsck_handle_write_error(io_channel channel, unsigned long block, int count, const void *data, size_t size EXT2FS_ATTR((unused)), int actual EXT2FS_ATTR((unused)), errcode_t error) { int i; const char *p; ext2_filsys fs = (ext2_filsys) channel->app_data; e2fsck_t ctx; ctx = (e2fsck_t) fs->priv_data; if (ctx->flags & E2F_FLAG_EXITING) return 0; /* * If more than one block was written, try writing each block * separately. We could use the actual bytes read to figure * out where to start, but we don't bother. */ if (count > 1) { p = (const char *) data; for (i=0; i < count; i++, p += channel->block_size, block++) { error = io_channel_write_blk(channel, block, 1, p); if (error) return error; } return 0; } if (operation) printf(_("Error writing block %lu (%s) while %s. "), block, error_message(error), operation); else printf(_("Error writing block %lu (%s). "), block, error_message(error)); preenhalt(ctx); if (ask(ctx, _("Ignore error"), 1)) return 0; return error; } const char *ehandler_operation(const char *op) { const char *ret = operation; operation = op; return ret; } void ehandler_init(io_channel channel) { channel->read_error = e2fsck_handle_read_error; channel->write_error = e2fsck_handle_write_error; }