Whamcloud - gitweb
debugfs: add support to display details of extended attribute structures
[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         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
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             xattr_dump = 0;
178         int             c, err;
179
180         if (check_fs_open(argv[0]))
181                 return;
182
183         reset_getopt();
184         while ((c = getopt (argc, argv, "f:x")) != EOF) {
185                 switch (c) {
186                 case 'f':
187                         file = optarg;
188                         break;
189                 case 'x':
190                         xattr_dump = 1;
191                         break;
192                 default:
193                         goto print_usage;
194                 }
195         }
196
197         if (argc != optind + 1) {
198         print_usage:
199                 com_err(0, 0, "Usage: block_dump [-x] [-f inode] block_num");
200                 return;
201         }
202
203         block = parse_ulonglong(argv[optind], argv[0], "block", &err);
204         if (err)
205                 return;
206
207         if (file) {
208                 inode = string_to_inode(file);
209                 if (!inode)
210                         return;
211                 errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0,
212                                        block, 0, &block);
213                 if (errcode) {
214                         com_err(argv[0], errcode,
215                                 "while mapping logical block %llu\n", block);
216                         return;
217                 }
218         }
219
220         buf = malloc(current_fs->blocksize);
221         if (!buf) {
222                 com_err(argv[0], 0, "Couldn't allocate block buffer");
223                 return;
224         }
225
226         errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
227         if (errcode) {
228                 com_err(argv[0], errcode,
229                         "while reading block %llu\n", block);
230                 goto errout;
231         }
232
233         if (xattr_dump)
234                 block_xattr_dump(stdout, buf, current_fs->blocksize);
235         else
236                 do_byte_hexdump(stdout, buf, current_fs->blocksize);
237 errout:
238         free(buf);
239 }
240
241 void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize)
242 {
243         size_t          i, j, max;
244         int             suppress = -1;
245
246         for (i = 0; i < bufsize; i += 16) {
247                 max = (bufsize - i > 16) ? 16 : bufsize - i;
248                 if (suppress < 0) {
249                         if (i && memcmp(buf + i, buf + i - max, max) == 0) {
250                                 suppress = i;
251                                 fprintf(fp, "*\n");
252                                 continue;
253                         }
254                 } else {
255                         if (memcmp(buf + i, buf + suppress, max) == 0)
256                                 continue;
257                         suppress = -1;
258                 }
259                 fprintf(fp, "%04o  ", (unsigned int)i);
260                 for (j = 0; j < 16; j++) {
261                         if (j < max)
262                                 fprintf(fp, "%02x", buf[i+j]);
263                         else
264                                 fprintf(fp, "  ");
265                         if ((j % 2) == 1)
266                                 fprintf(fp, " ");
267                 }
268                 fprintf(fp, " ");
269                 for (j = 0; j < max; j++)
270                         fprintf(fp, "%c", isprint(buf[i+j]) ? buf[i+j] : '.');
271                 fprintf(fp, "\n");
272         }
273         fprintf(fp, "\n");
274 }