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