zap.c revision dba2bbdfea74b482d4f3b6a3813a71c2358e57d6
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
22extern int optind;
23extern char *optarg;
24#endif
25
26#include "debugfs.h"
27
28void 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
165errout:
166	free(buf);
167	return;
168}
169
170void 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	unsigned int	i, j;
178	int		c, err;
179	int		suppress = -1;
180
181	if (check_fs_open(argv[0]))
182		return;
183
184	reset_getopt();
185	while ((c = getopt (argc, argv, "f:")) != EOF) {
186		switch (c) {
187		case 'f':
188			file = optarg;
189			break;
190
191		default:
192			goto print_usage;
193		}
194	}
195
196	if (argc != optind + 1) {
197	print_usage:
198		com_err(0, 0, "Usage: block_dump [-f inode] block_num");
199		return;
200	}
201
202	block = parse_ulonglong(argv[optind], argv[0], "block", &err);
203	if (err)
204		return;
205
206	if (file) {
207		inode = string_to_inode(file);
208		if (!inode)
209			return;
210		errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0,
211				       block, 0, &block);
212		if (errcode) {
213			com_err(argv[0], errcode,
214				"while mapping logical block %llu\n", block);
215			return;
216		}
217	}
218
219	buf = malloc(current_fs->blocksize);
220	if (!buf) {
221		com_err(argv[0], 0, "Couldn't allocate block buffer");
222		return;
223	}
224
225	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
226	if (errcode) {
227		com_err(argv[0], errcode,
228			"while reading block %llu\n", block);
229		goto errout;
230	}
231
232	for (i=0; i < current_fs->blocksize; i += 16) {
233		if (suppress < 0) {
234			if (i && memcmp(buf + i, buf + i - 16, 16) == 0) {
235				suppress = i;
236				printf("*\n");
237				continue;
238			}
239		} else {
240			if (memcmp(buf + i, buf + suppress, 16) == 0)
241				continue;
242			suppress = -1;
243		}
244		printf("%04o  ", i);
245		for (j = 0; j < 16; j++) {
246			printf("%02x", buf[i+j]);
247			if ((j % 2) == 1)
248				putchar(' ');
249		}
250		putchar(' ');
251		for (j = 0; j < 16; j++)
252			printf("%c", isprint(buf[i+j]) ? buf[i+j] : '.');
253		putchar('\n');
254	}
255	putchar('\n');
256
257errout:
258	free(buf);
259	return;
260}
261