zap.c revision dba2bbdfea74b482d4f3b6a3813a71c2358e57d6
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 22extern int optind; 23extern char *optarg; 24#endif 25 26#include "debugfs.h" 27 28void 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 165errout: 166 free(buf); 167 return; 168} 169 170void 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 unsigned int i, j; 178 int c, err; 179 int suppress = -1; 180 181 if (check_fs_open(argv[0])) 182 return; 183 184 reset_getopt(); 185 while ((c = getopt (argc, argv, "f:")) != EOF) { 186 switch (c) { 187 case 'f': 188 file = optarg; 189 break; 190 191 default: 192 goto print_usage; 193 } 194 } 195 196 if (argc != optind + 1) { 197 print_usage: 198 com_err(0, 0, "Usage: block_dump [-f inode] block_num"); 199 return; 200 } 201 202 block = parse_ulonglong(argv[optind], argv[0], "block", &err); 203 if (err) 204 return; 205 206 if (file) { 207 inode = string_to_inode(file); 208 if (!inode) 209 return; 210 errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0, 211 block, 0, &block); 212 if (errcode) { 213 com_err(argv[0], errcode, 214 "while mapping logical block %llu\n", block); 215 return; 216 } 217 } 218 219 buf = malloc(current_fs->blocksize); 220 if (!buf) { 221 com_err(argv[0], 0, "Couldn't allocate block buffer"); 222 return; 223 } 224 225 errcode = io_channel_read_blk64(current_fs->io, block, 1, buf); 226 if (errcode) { 227 com_err(argv[0], errcode, 228 "while reading block %llu\n", block); 229 goto errout; 230 } 231 232 for (i=0; i < current_fs->blocksize; i += 16) { 233 if (suppress < 0) { 234 if (i && memcmp(buf + i, buf + i - 16, 16) == 0) { 235 suppress = i; 236 printf("*\n"); 237 continue; 238 } 239 } else { 240 if (memcmp(buf + i, buf + suppress, 16) == 0) 241 continue; 242 suppress = -1; 243 } 244 printf("%04o ", i); 245 for (j = 0; j < 16; j++) { 246 printf("%02x", buf[i+j]); 247 if ((j % 2) == 1) 248 putchar(' '); 249 } 250 putchar(' '); 251 for (j = 0; j < 16; j++) 252 printf("%c", isprint(buf[i+j]) ? buf[i+j] : '.'); 253 putchar('\n'); 254 } 255 putchar('\n'); 256 257errout: 258 free(buf); 259 return; 260} 261