Home | History | Annotate | Download | only in e2fsck
      1 /*
      2  * ehandler.c --- handle bad block errors which come up during the
      3  * 	course of an e2fsck session.
      4  *
      5  * Copyright (C) 1994 Theodore Ts'o.  This file may be redistributed
      6  * under the terms of the GNU Public License.
      7  */
      8 
      9 #include "config.h"
     10 #include <stdlib.h>
     11 #include <unistd.h>
     12 #include <string.h>
     13 #include <ctype.h>
     14 #include <termios.h>
     15 
     16 #include "e2fsck.h"
     17 
     18 #include <sys/time.h>
     19 #include <sys/resource.h>
     20 
     21 static const char *operation;
     22 
     23 static errcode_t e2fsck_handle_read_error(io_channel channel,
     24 					  unsigned long block,
     25 					  int count,
     26 					  void *data,
     27 					  size_t size EXT2FS_ATTR((unused)),
     28 					  int actual EXT2FS_ATTR((unused)),
     29 					  errcode_t error)
     30 {
     31 	int	i;
     32 	char	*p;
     33 	ext2_filsys fs = (ext2_filsys) channel->app_data;
     34 	e2fsck_t ctx;
     35 
     36 	ctx = (e2fsck_t) fs->priv_data;
     37 	if (ctx->flags & E2F_FLAG_EXITING)
     38 		return 0;
     39 	/*
     40 	 * If more than one block was read, try reading each block
     41 	 * separately.  We could use the actual bytes read to figure
     42 	 * out where to start, but we don't bother.
     43 	 */
     44 	if (count > 1) {
     45 		p = (char *) data;
     46 		for (i=0; i < count; i++, p += channel->block_size, block++) {
     47 			error = io_channel_read_blk64(channel, block,
     48 						    1, p);
     49 			if (error)
     50 				return error;
     51 		}
     52 		return 0;
     53 	}
     54 	if (operation)
     55 		printf(_("Error reading block %lu (%s) while %s.  "), block,
     56 		       error_message(error), operation);
     57 	else
     58 		printf(_("Error reading block %lu (%s).  "), block,
     59 		       error_message(error));
     60 	preenhalt(ctx);
     61 
     62 	/* Don't rewrite a block past the end of the FS. */
     63 	if (block >= ext2fs_blocks_count(fs->super))
     64 		return 0;
     65 
     66 	if (ask(ctx, _("Ignore error"), 1)) {
     67 		if (ask(ctx, _("Force rewrite"), 1))
     68 			io_channel_write_blk64(channel, block, count, data);
     69 		return 0;
     70 	}
     71 
     72 	return error;
     73 }
     74 
     75 static errcode_t e2fsck_handle_write_error(io_channel channel,
     76 					    unsigned long block,
     77 					    int count,
     78 					    const void *data,
     79 					    size_t size EXT2FS_ATTR((unused)),
     80 					    int actual EXT2FS_ATTR((unused)),
     81 					    errcode_t error)
     82 {
     83 	int		i;
     84 	const char	*p;
     85 	ext2_filsys fs = (ext2_filsys) channel->app_data;
     86 	e2fsck_t ctx;
     87 
     88 	ctx = (e2fsck_t) fs->priv_data;
     89 	if (ctx->flags & E2F_FLAG_EXITING)
     90 		return 0;
     91 
     92 	/*
     93 	 * If more than one block was written, try writing each block
     94 	 * separately.  We could use the actual bytes read to figure
     95 	 * out where to start, but we don't bother.
     96 	 */
     97 	if (count > 1) {
     98 		p = (const char *) data;
     99 		for (i=0; i < count; i++, p += channel->block_size, block++) {
    100 			error = io_channel_write_blk64(channel, block,
    101 						     1, p);
    102 			if (error)
    103 				return error;
    104 		}
    105 		return 0;
    106 	}
    107 
    108 	if (operation)
    109 		printf(_("Error writing block %lu (%s) while %s.  "), block,
    110 		       error_message(error), operation);
    111 	else
    112 		printf(_("Error writing block %lu (%s).  "), block,
    113 		       error_message(error));
    114 	preenhalt(ctx);
    115 	if (ask(ctx, _("Ignore error"), 1))
    116 		return 0;
    117 
    118 	return error;
    119 }
    120 
    121 const char *ehandler_operation(const char *op)
    122 {
    123 	const char *ret = operation;
    124 
    125 	operation = op;
    126 	return ret;
    127 }
    128 
    129 void ehandler_init(io_channel channel)
    130 {
    131 	channel->read_error = e2fsck_handle_read_error;
    132 	channel->write_error = e2fsck_handle_write_error;
    133 }
    134