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