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