• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
e2fsck_handle_read_error(io_channel channel,unsigned long block,int count,void * data,size_t size EXT2FS_ATTR ((unused)),int actual EXT2FS_ATTR ((unused)),errcode_t error)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 
e2fsck_handle_write_error(io_channel channel,unsigned long block,int count,const void * data,size_t size EXT2FS_ATTR ((unused)),int actual EXT2FS_ATTR ((unused)),errcode_t error)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 
ehandler_operation(const char * op)121 const char *ehandler_operation(const char *op)
122 {
123 	const char *ret = operation;
124 
125 	operation = op;
126 	return ret;
127 }
128 
ehandler_init(io_channel channel)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