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