• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * zap.c --- zap block
3  *
4  * Copyright (C) 2012 Theodore Ts'o.  This file may be redistributed
5  * under the terms of the GNU Public License.
6  */
7 
8 #include "config.h"
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13 #include <string.h>
14 #include <time.h>
15 #ifdef HAVE_ERRNO_H
16 #include <errno.h>
17 #endif
18 #include <sys/types.h>
19 #ifdef HAVE_GETOPT_H
20 #include <getopt.h>
21 #else
22 extern int optind;
23 extern char *optarg;
24 #endif
25 
26 #include "debugfs.h"
27 
do_zap_block(int argc,char * argv[])28 void do_zap_block(int argc, char *argv[])
29 {
30 	unsigned long	pattern = 0;
31 	unsigned char	*buf;
32 	ext2_ino_t	inode;
33 	errcode_t	errcode;
34 	blk64_t		block;
35 	char		*file = NULL;
36 	int		c, err;
37 	int		offset = -1;
38 	int		length = -1;
39 	int		bit = -1;
40 
41 	if (check_fs_open(argv[0]))
42 		return;
43 	if (check_fs_read_write(argv[0]))
44 		return;
45 
46 	reset_getopt();
47 	while ((c = getopt (argc, argv, "b:f:l:o:p:")) != EOF) {
48 		switch (c) {
49 		case 'f':
50 			file = optarg;
51 			break;
52 		case 'b':
53 			bit = parse_ulong(optarg, argv[0],
54 					  "bit", &err);
55 			if (err)
56 				return;
57 			if (bit >= (int) current_fs->blocksize * 8) {
58 				com_err(argv[0], 0, "The bit to flip "
59 					"must be within a %d block\n",
60 					current_fs->blocksize);
61 				return;
62 			}
63 			break;
64 		case 'p':
65 			pattern = parse_ulong(optarg, argv[0],
66 					      "pattern", &err);
67 			if (err)
68 				return;
69 			if (pattern >= 256) {
70 				com_err(argv[0], 0, "The fill pattern must "
71 					"be an 8-bit value\n");
72 				return;
73 			}
74 			break;
75 		case 'o':
76 			offset = parse_ulong(optarg, argv[0],
77 					     "offset", &err);
78 			if (err)
79 				return;
80 			if (offset >= (int) current_fs->blocksize) {
81 				com_err(argv[0], 0, "The offset must be "
82 					"within a %d block\n",
83 					current_fs->blocksize);
84 				return;
85 			}
86 			break;
87 
88 			break;
89 		case 'l':
90 			length = parse_ulong(optarg, argv[0],
91 					     "length", &err);
92 			if (err)
93 				return;
94 			break;
95 		default:
96 			goto print_usage;
97 		}
98 	}
99 
100 	if (bit > 0 && offset > 0) {
101 		com_err(argv[0], 0, "The -o and -b options can not be mixed.");
102 		return;
103 	}
104 
105 	if (offset < 0)
106 		offset = 0;
107 	if (length < 0)
108 		length = current_fs->blocksize - offset;
109 	if ((offset + length) > (int) current_fs->blocksize) {
110 		com_err(argv[0], 0, "The specified length is too bug\n");
111 		return;
112 	}
113 
114 	if (argc != optind+1) {
115 	print_usage:
116 		com_err(0, 0, "Usage:\tzap_block [-f file] [-o offset] "
117 			"[-l length] [-p pattern] block_num");
118 		com_err(0, 0, "\tzap_block [-f file] [-b bit] "
119 			"block_num");
120 		return;
121 	}
122 
123 	block = parse_ulonglong(argv[optind], argv[0], "block", &err);
124 	if (err)
125 		return;
126 
127 	if (file) {
128 		inode = string_to_inode(file);
129 		if (!inode)
130 			return;
131 		errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0,
132 				       block, 0, &block);
133 		if (errcode) {
134 			com_err(argv[0], errcode,
135 				"while mapping logical block %llu\n", block);
136 			return;
137 		}
138 	}
139 
140 	buf = malloc(current_fs->blocksize);
141 	if (!buf) {
142 		com_err(argv[0], 0, "Couldn't allocate block buffer");
143 		return;
144 	}
145 
146 	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
147 	if (errcode) {
148 		com_err(argv[0], errcode,
149 			"while reading block %llu\n", block);
150 		goto errout;
151 	}
152 
153 	if (bit >= 0)
154 		buf[bit >> 3] ^= 1 << (bit & 7);
155 	else
156 		memset(buf+offset, pattern, length);
157 
158 	errcode = io_channel_write_blk64(current_fs->io, block, 1, buf);
159 	if (errcode) {
160 		com_err(argv[0], errcode,
161 			"while write block %llu\n", block);
162 		goto errout;
163 	}
164 
165 errout:
166 	free(buf);
167 	return;
168 }
169 
do_block_dump(int argc,char * argv[])170 void do_block_dump(int argc, char *argv[])
171 {
172 	unsigned char	*buf;
173 	ext2_ino_t	inode;
174 	errcode_t	errcode;
175 	blk64_t		block;
176 	char		*file = NULL;
177 	int		c, err;
178 
179 	if (check_fs_open(argv[0]))
180 		return;
181 
182 	reset_getopt();
183 	while ((c = getopt (argc, argv, "f:")) != EOF) {
184 		switch (c) {
185 		case 'f':
186 			file = optarg;
187 			break;
188 
189 		default:
190 			goto print_usage;
191 		}
192 	}
193 
194 	if (argc != optind + 1) {
195 	print_usage:
196 		com_err(0, 0, "Usage: block_dump [-f inode] block_num");
197 		return;
198 	}
199 
200 	block = parse_ulonglong(argv[optind], argv[0], "block", &err);
201 	if (err)
202 		return;
203 
204 	if (file) {
205 		inode = string_to_inode(file);
206 		if (!inode)
207 			return;
208 		errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0,
209 				       block, 0, &block);
210 		if (errcode) {
211 			com_err(argv[0], errcode,
212 				"while mapping logical block %llu\n", block);
213 			return;
214 		}
215 	}
216 
217 	buf = malloc(current_fs->blocksize);
218 	if (!buf) {
219 		com_err(argv[0], 0, "Couldn't allocate block buffer");
220 		return;
221 	}
222 
223 	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
224 	if (errcode) {
225 		com_err(argv[0], errcode,
226 			"while reading block %llu\n", block);
227 		goto errout;
228 	}
229 
230 	do_byte_hexdump(stdout, buf, current_fs->blocksize);
231 errout:
232 	free(buf);
233 }
234 
do_byte_hexdump(FILE * fp,unsigned char * buf,size_t bufsize)235 void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize)
236 {
237 	size_t		i, j;
238 	int		suppress = -1;
239 
240 	for (i = 0; i < bufsize; i += 16) {
241 		if (suppress < 0) {
242 			if (i && memcmp(buf + i, buf + i - 16, 16) == 0) {
243 				suppress = i;
244 				fprintf(fp, "*\n");
245 				continue;
246 			}
247 		} else {
248 			if (memcmp(buf + i, buf + suppress, 16) == 0)
249 				continue;
250 			suppress = -1;
251 		}
252 		fprintf(fp, "%04o  ", (unsigned int)i);
253 		for (j = 0; j < 16; j++) {
254 			fprintf(fp, "%02x", buf[i+j]);
255 			if ((j % 2) == 1)
256 				fprintf(fp, " ");
257 		}
258 		fprintf(fp, " ");
259 		for (j = 0; j < 16; j++)
260 			fprintf(fp, "%c", isprint(buf[i+j]) ? buf[i+j] : '.');
261 		fprintf(fp, "\n");
262 	}
263 	fprintf(fp, "\n");
264 }
265