]>
Commit | Line | Data |
---|---|---|
ba75d9e2 TT |
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 | ||
2fcbcb1b TT |
28 | void do_zap_block(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), |
29 | void *infop EXT2FS_ATTR((unused))) | |
ba75d9e2 TT |
30 | { |
31 | unsigned long pattern = 0; | |
32 | unsigned char *buf; | |
33 | ext2_ino_t inode; | |
34 | errcode_t errcode; | |
35 | blk64_t block; | |
ba75d9e2 | 36 | char *file = NULL; |
ba75d9e2 TT |
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; | |
9e85208e | 58 | if (bit >= (int) current_fs->blocksize * 8) { |
ba75d9e2 TT |
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; | |
9e85208e | 81 | if (offset >= (int) current_fs->blocksize) { |
ba75d9e2 TT |
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; | |
9e85208e | 110 | if ((offset + length) > (int) current_fs->blocksize) { |
ba75d9e2 TT |
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 | ||
2fcbcb1b TT |
171 | void do_block_dump(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), |
172 | void *infop EXT2FS_ATTR((unused))) | |
ba75d9e2 | 173 | { |
ba75d9e2 TT |
174 | unsigned char *buf; |
175 | ext2_ino_t inode; | |
176 | errcode_t errcode; | |
177 | blk64_t block; | |
ba75d9e2 | 178 | char *file = NULL; |
c7c99af6 | 179 | int xattr_dump = 0; |
9e85208e | 180 | int c, err; |
ba75d9e2 TT |
181 | |
182 | if (check_fs_open(argv[0])) | |
183 | return; | |
184 | ||
185 | reset_getopt(); | |
c7c99af6 | 186 | while ((c = getopt (argc, argv, "f:x")) != EOF) { |
ba75d9e2 TT |
187 | switch (c) { |
188 | case 'f': | |
189 | file = optarg; | |
190 | break; | |
c7c99af6 TT |
191 | case 'x': |
192 | xattr_dump = 1; | |
193 | break; | |
ba75d9e2 TT |
194 | default: |
195 | goto print_usage; | |
196 | } | |
197 | } | |
198 | ||
dba2bbdf | 199 | if (argc != optind + 1) { |
ba75d9e2 | 200 | print_usage: |
c7c99af6 | 201 | com_err(0, 0, "Usage: block_dump [-x] [-f inode] block_num"); |
ba75d9e2 TT |
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 | ||
c7c99af6 TT |
235 | if (xattr_dump) |
236 | block_xattr_dump(stdout, buf, current_fs->blocksize); | |
237 | else | |
238 | do_byte_hexdump(stdout, buf, current_fs->blocksize); | |
e13ebfdd DW |
239 | errout: |
240 | free(buf); | |
241 | } | |
242 | ||
243 | void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize) | |
244 | { | |
dd1543db | 245 | size_t i, j, max; |
e13ebfdd DW |
246 | int suppress = -1; |
247 | ||
248 | for (i = 0; i < bufsize; i += 16) { | |
dd1543db | 249 | max = (bufsize - i > 16) ? 16 : bufsize - i; |
ba75d9e2 | 250 | if (suppress < 0) { |
dd1543db | 251 | if (i && memcmp(buf + i, buf + i - max, max) == 0) { |
ba75d9e2 | 252 | suppress = i; |
e13ebfdd | 253 | fprintf(fp, "*\n"); |
ba75d9e2 TT |
254 | continue; |
255 | } | |
256 | } else { | |
dd1543db | 257 | if (memcmp(buf + i, buf + suppress, max) == 0) |
ba75d9e2 TT |
258 | continue; |
259 | suppress = -1; | |
260 | } | |
e13ebfdd | 261 | fprintf(fp, "%04o ", (unsigned int)i); |
ba75d9e2 | 262 | for (j = 0; j < 16; j++) { |
dd1543db TT |
263 | if (j < max) |
264 | fprintf(fp, "%02x", buf[i+j]); | |
265 | else | |
266 | fprintf(fp, " "); | |
ba75d9e2 | 267 | if ((j % 2) == 1) |
e13ebfdd | 268 | fprintf(fp, " "); |
ba75d9e2 | 269 | } |
e13ebfdd | 270 | fprintf(fp, " "); |
dd1543db | 271 | for (j = 0; j < max; j++) |
e13ebfdd DW |
272 | fprintf(fp, "%c", isprint(buf[i+j]) ? buf[i+j] : '.'); |
273 | fprintf(fp, "\n"); | |
ba75d9e2 | 274 | } |
e13ebfdd | 275 | fprintf(fp, "\n"); |
ba75d9e2 | 276 | } |