diff options
Diffstat (limited to 'e2fsck/ehandler.c')
-rw-r--r-- | e2fsck/ehandler.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/e2fsck/ehandler.c b/e2fsck/ehandler.c new file mode 100644 index 0000000..71ca301 --- /dev/null +++ b/e2fsck/ehandler.c @@ -0,0 +1,133 @@ +/* + * 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 "config.h" +#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_blk64(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); + + /* Don't rewrite a block past the end of the FS. */ + if (block >= ext2fs_blocks_count(fs->super)) + return 0; + + if (ask(ctx, _("Ignore error"), 1)) { + if (ask(ctx, _("Force rewrite"), 1)) + io_channel_write_blk64(channel, block, count, 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_blk64(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; +} |