zap.c revision 18a1444b4f1e6a0948fd38fa0de382d86cfe04de
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 21extern int optind; 22extern char *optarg; 23#endif 24 25#include "debugfs.h" 26 27void 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 164errout: 165 free(buf); 166 return; 167} 168 169void 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 256errout: 257 free(buf); 258 return; 259} 260