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