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