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