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