blob: f9021f060da0e4fc45fb7943ef15e9c0bc92ebbd [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * ehandler.c --- handle bad block errors which come up during the
3 * course of an e2fsck session.
Theodore Ts'oefc6f622008-08-27 23:07:54 -04004 *
Theodore Ts'o3839e651997-04-26 13:21:57 +00005 * 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>
Theodore Ts'o3839e651997-04-26 13:21:57 +000014
15#include "e2fsck.h"
16
Theodore Ts'o50e1e101997-04-26 13:58:21 +000017#include <sys/time.h>
18#include <sys/resource.h>
19
Theodore Ts'o3839e651997-04-26 13:21:57 +000020static const char *operation;
21
22static errcode_t e2fsck_handle_read_error(io_channel channel,
23 unsigned long block,
24 int count,
25 void *data,
Theodore Ts'o54434922003-12-07 01:28:50 -050026 size_t size EXT2FS_ATTR((unused)),
27 int actual EXT2FS_ATTR((unused)),
Theodore Ts'o3839e651997-04-26 13:21:57 +000028 errcode_t error)
29{
30 int i;
31 char *p;
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +000032 ext2_filsys fs = (ext2_filsys) channel->app_data;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000033 e2fsck_t ctx;
34
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +000035 ctx = (e2fsck_t) fs->priv_data;
Eric Sandeen79cc3362008-10-10 17:14:08 -050036 if (ctx->flags & E2F_FLAG_EXITING)
37 return 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +000038 /*
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)
Theodore Ts'o0c4a0722000-02-07 03:11:03 +000054 printf(_("Error reading block %lu (%s) while %s. "), block,
Theodore Ts'o3839e651997-04-26 13:21:57 +000055 error_message(error), operation);
56 else
Theodore Ts'o0c4a0722000-02-07 03:11:03 +000057 printf(_("Error reading block %lu (%s). "), block,
Theodore Ts'o3839e651997-04-26 13:21:57 +000058 error_message(error));
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000059 preenhalt(ctx);
Theodore Ts'oceecbc72002-08-31 02:35:35 -040060 if (ask(ctx, _("Ignore error"), 1)) {
61 if (ask(ctx, _("Force rewrite"), 1))
62 io_channel_write_blk(channel, block, 1, data);
Theodore Ts'o3839e651997-04-26 13:21:57 +000063 return 0;
Theodore Ts'oceecbc72002-08-31 02:35:35 -040064 }
Theodore Ts'o3839e651997-04-26 13:21:57 +000065
66 return error;
67}
68
69static errcode_t e2fsck_handle_write_error(io_channel channel,
70 unsigned long block,
71 int count,
72 const void *data,
Theodore Ts'o54434922003-12-07 01:28:50 -050073 size_t size EXT2FS_ATTR((unused)),
74 int actual EXT2FS_ATTR((unused)),
Theodore Ts'o3839e651997-04-26 13:21:57 +000075 errcode_t error)
76{
77 int i;
78 const char *p;
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +000079 ext2_filsys fs = (ext2_filsys) channel->app_data;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000080 e2fsck_t ctx;
Theodore Ts'oefc6f622008-08-27 23:07:54 -040081
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +000082 ctx = (e2fsck_t) fs->priv_data;
Eric Sandeen79cc3362008-10-10 17:14:08 -050083 if (ctx->flags & E2F_FLAG_EXITING)
84 return 0;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000085
Theodore Ts'o3839e651997-04-26 13:21:57 +000086 /*
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 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400101
Theodore Ts'o3839e651997-04-26 13:21:57 +0000102 if (operation)
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000103 printf(_("Error writing block %lu (%s) while %s. "), block,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000104 error_message(error), operation);
105 else
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000106 printf(_("Error writing block %lu (%s). "), block,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000107 error_message(error));
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000108 preenhalt(ctx);
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000109 if (ask(ctx, _("Ignore error"), 1))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000110 return 0;
111
112 return error;
113}
114
115const char *ehandler_operation(const char *op)
116{
117 const char *ret = operation;
118
119 operation = op;
120 return ret;
121}
122
123void ehandler_init(io_channel channel)
124{
125 channel->read_error = e2fsck_handle_read_error;
126 channel->write_error = e2fsck_handle_write_error;
127}