]>
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 | ||
49125d40 | 28 | void do_zap_block(int argc, ss_argv_t argv, int sci_idx EXT2FS_ATTR((unused)), |
2fcbcb1b | 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, | |
33b9a60c TT |
136 | "while mapping logical block %llu\n", |
137 | (unsigned long long) block); | |
ba75d9e2 TT |
138 | return; |
139 | } | |
140 | } | |
141 | ||
142 | buf = malloc(current_fs->blocksize); | |
143 | if (!buf) { | |
144 | com_err(argv[0], 0, "Couldn't allocate block buffer"); | |
145 | return; | |
146 | } | |
147 | ||
148 | errcode = io_channel_read_blk64(current_fs->io, block, 1, buf); | |
149 | if (errcode) { | |
150 | com_err(argv[0], errcode, | |
33b9a60c TT |
151 | "while reading block %llu\n", |
152 | (unsigned long long) block); | |
ba75d9e2 TT |
153 | goto errout; |
154 | } | |
155 | ||
156 | if (bit >= 0) | |
157 | buf[bit >> 3] ^= 1 << (bit & 7); | |
158 | else | |
159 | memset(buf+offset, pattern, length); | |
160 | ||
161 | errcode = io_channel_write_blk64(current_fs->io, block, 1, buf); | |
162 | if (errcode) { | |
163 | com_err(argv[0], errcode, | |
33b9a60c TT |
164 | "while write block %llu\n", |
165 | (unsigned long long) block); | |
ba75d9e2 TT |
166 | goto errout; |
167 | } | |
168 | ||
169 | errout: | |
170 | free(buf); | |
171 | return; | |
172 | } | |
173 | ||
49125d40 | 174 | void do_block_dump(int argc, ss_argv_t argv, int sci_idx EXT2FS_ATTR((unused)), |
2fcbcb1b | 175 | void *infop EXT2FS_ATTR((unused))) |
ba75d9e2 | 176 | { |
ba75d9e2 TT |
177 | unsigned char *buf; |
178 | ext2_ino_t inode; | |
179 | errcode_t errcode; | |
180 | blk64_t block; | |
ba75d9e2 | 181 | char *file = NULL; |
c7c99af6 | 182 | int xattr_dump = 0; |
9e85208e | 183 | int c, err; |
ba75d9e2 TT |
184 | |
185 | if (check_fs_open(argv[0])) | |
186 | return; | |
187 | ||
188 | reset_getopt(); | |
c7c99af6 | 189 | while ((c = getopt (argc, argv, "f:x")) != EOF) { |
ba75d9e2 TT |
190 | switch (c) { |
191 | case 'f': | |
192 | file = optarg; | |
193 | break; | |
c7c99af6 TT |
194 | case 'x': |
195 | xattr_dump = 1; | |
196 | break; | |
ba75d9e2 TT |
197 | default: |
198 | goto print_usage; | |
199 | } | |
200 | } | |
201 | ||
dba2bbdf | 202 | if (argc != optind + 1) { |
ba75d9e2 | 203 | print_usage: |
c7c99af6 | 204 | com_err(0, 0, "Usage: block_dump [-x] [-f inode] block_num"); |
ba75d9e2 TT |
205 | return; |
206 | } | |
207 | ||
208 | block = parse_ulonglong(argv[optind], argv[0], "block", &err); | |
209 | if (err) | |
210 | return; | |
211 | ||
212 | if (file) { | |
213 | inode = string_to_inode(file); | |
214 | if (!inode) | |
215 | return; | |
216 | errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0, | |
217 | block, 0, &block); | |
218 | if (errcode) { | |
219 | com_err(argv[0], errcode, | |
33b9a60c TT |
220 | "while mapping logical block %llu\n", |
221 | (unsigned long long) block); | |
ba75d9e2 TT |
222 | return; |
223 | } | |
224 | } | |
225 | ||
226 | buf = malloc(current_fs->blocksize); | |
227 | if (!buf) { | |
228 | com_err(argv[0], 0, "Couldn't allocate block buffer"); | |
229 | return; | |
230 | } | |
231 | ||
232 | errcode = io_channel_read_blk64(current_fs->io, block, 1, buf); | |
233 | if (errcode) { | |
234 | com_err(argv[0], errcode, | |
33b9a60c TT |
235 | "while reading block %llu\n", |
236 | (unsigned long long) block); | |
ba75d9e2 TT |
237 | goto errout; |
238 | } | |
239 | ||
c7c99af6 TT |
240 | if (xattr_dump) |
241 | block_xattr_dump(stdout, buf, current_fs->blocksize); | |
242 | else | |
243 | do_byte_hexdump(stdout, buf, current_fs->blocksize); | |
e13ebfdd DW |
244 | errout: |
245 | free(buf); | |
246 | } |