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