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 <stdlib.h>
     10 #include <unistd.h>
     11 #include <string.h>
     12 #include <ctype.h>
     13 #include <termios.h>
     14 
     15 #include "e2fsck.h"
     16 
     17 #include <sys/time.h>
     18 #include <sys/resource.h>
     19 
     20 static const char *operation;
     21 
     22 static errcode_t e2fsck_handle_read_error(io_channel channel,
     23 					  unsigned long block,
     24 					  int count,
     25 					  void *data,
     26 					  size_t size EXT2FS_ATTR((unused)),
     27 					  int actual EXT2FS_ATTR((unused)),
     28 					  errcode_t error)
     29 {
     30 	int	i;
     31 	char	*p;
     32 	ext2_filsys fs = (ext2_filsys) channel->app_data;
     33 	e2fsck_t ctx;
     34 
     35 	ctx = (e2fsck_t) fs->priv_data;
     36 	if (ctx->flags & E2F_FLAG_EXITING)
     37 		return 0;
     38 	/*
     39 	 * If more than one block was read, try reading each block
     40 	 * separately.  We could use the actual bytes read to figure
     41 	 * out where to start, but we don't bother.
     42 	 */
     43 	if (count > 1) {
     44 		p = (char *) data;
     45 		for (i=0; i < count; i++, p += channel->block_size, block++) {
     46 			error = io_channel_read_blk(channel, block,
     47 						    1, p);
     48 			if (error)
     49 				return error;
     50 		}
     51 		return 0;
     52 	}
     53 	if (operation)
     54 		printf(_("Error reading block %lu (%s) while %s.  "), block,
     55 		       error_message(error), operation);
     56 	else
     57 		printf(_("Error reading block %lu (%s).  "), block,
     58 		       error_message(error));
     59 	preenhalt(ctx);
     60 	if (ask(ctx, _("Ignore error"), 1)) {
     61 		if (ask(ctx, _("Force rewrite"), 1))
     62 			io_channel_write_blk(channel, block, 1, data);
     63 		return 0;
     64 	}
     65 
     66 	return error;
     67 }
     68 
     69 static errcode_t e2fsck_handle_write_error(io_channel channel,
     70 					    unsigned long block,
     71 					    int count,
     72 					    const void *data,
     73 					    size_t size EXT2FS_ATTR((unused)),
     74 					    int actual EXT2FS_ATTR((unused)),
     75 					    errcode_t error)
     76 {
     77 	int		i;
     78 	const char	*p;
     79 	ext2_filsys fs = (ext2_filsys) channel->app_data;
     80 	e2fsck_t ctx;
     81 
     82 	ctx = (e2fsck_t) fs->priv_data;
     83 	if (ctx->flags & E2F_FLAG_EXITING)
     84 		return 0;
     85 
     86 	/*
     87 	 * If more than one block was written, try writing each block
     88 	 * separately.  We could use the actual bytes read to figure
     89 	 * out where to start, but we don't bother.
     90 	 */
     91 	if (count > 1) {
     92 		p = (const char *) data;
     93 		for (i=0; i < count; i++, p += channel->block_size, block++) {
     94 			error = io_channel_write_blk(channel, block,
     95 						     1, p);
     96 			if (error)
     97 				return error;
     98 		}
     99 		return 0;
    100 	}
    101 
    102 	if (operation)
    103 		printf(_("Error writing block %lu (%s) while %s.  "), block,
    104 		       error_message(error), operation);
    105 	else
    106 		printf(_("Error writing block %lu (%s).  "), block,
    107 		       error_message(error));
    108 	preenhalt(ctx);
    109 	if (ask(ctx, _("Ignore error"), 1))
    110 		return 0;
    111 
    112 	return error;
    113 }
    114 
    115 const char *ehandler_operation(const char *op)
    116 {
    117 	const char *ret = operation;
    118 
    119 	operation = op;
    120 	return ret;
    121 }
    122 
    123 void ehandler_init(io_channel channel)
    124 {
    125 	channel->read_error = e2fsck_handle_read_error;
    126 	channel->write_error = e2fsck_handle_write_error;
    127 }
    128