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