dumpe2fs.c revision 24dea55494ea753dbc8e4d965345cd2a7144d4fd
1/* 2 * dumpe2fs.c - List the control structures of a second 3 * extended filesystem 4 * 5 * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> 6 * Laboratoire MASI, Institut Blaise Pascal 7 * Universite Pierre et Marie Curie (Paris VI) 8 * 9 * Copyright 1995, 1996, 1997 by Theodore Ts'o. 10 * 11 * %Begin-Header% 12 * This file may be redistributed under the terms of the GNU Public 13 * License. 14 * %End-Header% 15 */ 16 17/* 18 * History: 19 * 94/01/09 - Creation 20 * 94/02/27 - Ported to use the ext2fs library 21 */ 22 23#include "config.h" 24#ifdef HAVE_GETOPT_H 25#include <getopt.h> 26#else 27extern char *optarg; 28extern int optind; 29#endif 30#include <fcntl.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34#include <unistd.h> 35 36#include "ext2fs/ext2_fs.h" 37 38#include "ext2fs/ext2fs.h" 39#include "e2p/e2p.h" 40#include "jfs_user.h" 41#include <uuid/uuid.h> 42 43#include "../version.h" 44#include "nls-enable.h" 45 46#define in_use(m, x) (ext2fs_test_bit ((x), (m))) 47 48const char * program_name = "dumpe2fs"; 49char * device_name = NULL; 50int hex_format = 0; 51 52static void usage(void) 53{ 54 fprintf (stderr, _("Usage: %s [-bfhixV] [-o superblock=<num>] " 55 "[-o blocksize=<num>] device\n"), program_name); 56 exit (1); 57} 58 59static void print_number(unsigned long num) 60{ 61 if (hex_format) 62 printf("0x%04lx", num); 63 else 64 printf("%lu", num); 65} 66 67static void print_range(unsigned long long a, unsigned long long b) 68{ 69 if (hex_format) 70 printf("0x%llx-0x%llx", a, b); 71 else 72 printf("%llu-%llu", a, b); 73} 74 75static void print_free(unsigned long group, char * bitmap, 76 unsigned long num, unsigned long offset, int ratio) 77{ 78 int p = 0; 79 unsigned long i; 80 unsigned long j; 81 82 offset /= ratio; 83 offset += group * num; 84 for (i = 0; i < num; i++) 85 if (!in_use (bitmap, i)) 86 { 87 if (p) 88 printf (", "); 89 print_number((i + offset) * ratio); 90 for (j = i; j < num && !in_use (bitmap, j); j++) 91 ; 92 if (--j != i) { 93 fputc('-', stdout); 94 print_number((j + offset) * ratio); 95 i = j; 96 } 97 p = 1; 98 } 99} 100 101static void print_bg_opt(int bg_flags, int mask, 102 const char *str, int *first) 103{ 104 if (bg_flags & mask) { 105 if (*first) { 106 fputs(" [", stdout); 107 *first = 0; 108 } else 109 fputs(", ", stdout); 110 fputs(str, stdout); 111 } 112} 113static void print_bg_opts(ext2_filsys fs, dgrp_t i) 114{ 115 int first = 1, bg_flags = 0; 116 117 if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) 118 bg_flags = ext2fs_bg_flags(fs, i); 119 120 print_bg_opt(bg_flags, EXT2_BG_INODE_UNINIT, "INODE_UNINIT", 121 &first); 122 print_bg_opt(bg_flags, EXT2_BG_BLOCK_UNINIT, "BLOCK_UNINIT", 123 &first); 124 print_bg_opt(bg_flags, EXT2_BG_INODE_ZEROED, "ITABLE_ZEROED", 125 &first); 126 if (!first) 127 fputc(']', stdout); 128 fputc('\n', stdout); 129} 130 131static void print_bg_rel_offset(ext2_filsys fs, blk64_t block, int itable, 132 blk64_t first_block, blk64_t last_block) 133{ 134 if ((block >= first_block) && (block <= last_block)) { 135 if (itable && block == first_block) 136 return; 137 printf(" (+%u)", (unsigned)(block - first_block)); 138 } else if (fs->super->s_feature_incompat & 139 EXT4_FEATURE_INCOMPAT_FLEX_BG) { 140 dgrp_t flex_grp = ext2fs_group_of_blk(fs, block); 141 printf(" (bg #%u + %u)", flex_grp, 142 (unsigned)(block-ext2fs_group_first_block(fs,flex_grp))); 143 } 144} 145 146static void list_desc (ext2_filsys fs) 147{ 148 unsigned long i; 149 blk64_t first_block, last_block; 150 blk64_t super_blk, old_desc_blk, new_desc_blk; 151 char *block_bitmap=NULL, *inode_bitmap=NULL; 152 const char *units = _("blocks"); 153 int inode_blocks_per_group, old_desc_blocks, reserved_gdt; 154 int block_nbytes, inode_nbytes; 155 int has_super; 156 blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); 157 ext2_ino_t ino_itr = 1; 158 159 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 160 EXT4_FEATURE_RO_COMPAT_BIGALLOC)) 161 units = _("clusters"); 162 163 block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; 164 inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; 165 166 if (fs->block_map) 167 block_bitmap = malloc(block_nbytes); 168 if (fs->inode_map) 169 inode_bitmap = malloc(inode_nbytes); 170 171 inode_blocks_per_group = ((fs->super->s_inodes_per_group * 172 EXT2_INODE_SIZE(fs->super)) + 173 EXT2_BLOCK_SIZE(fs->super) - 1) / 174 EXT2_BLOCK_SIZE(fs->super); 175 reserved_gdt = fs->super->s_reserved_gdt_blocks; 176 fputc('\n', stdout); 177 first_block = fs->super->s_first_data_block; 178 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 179 old_desc_blocks = fs->super->s_first_meta_bg; 180 else 181 old_desc_blocks = fs->desc_blocks; 182 for (i = 0; i < fs->group_desc_count; i++) { 183 first_block = ext2fs_group_first_block2(fs, i); 184 last_block = ext2fs_group_last_block2(fs, i); 185 186 ext2fs_super_and_bgd_loc2(fs, i, &super_blk, 187 &old_desc_blk, &new_desc_blk, 0); 188 189 printf (_("Group %lu: (Blocks "), i); 190 print_range(first_block, last_block); 191 fputs(")", stdout); 192 print_bg_opts(fs, i); 193 if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { 194 unsigned csum = ext2fs_bg_checksum(fs, i); 195 unsigned exp_csum = ext2fs_group_desc_csum(fs, i); 196 197 printf(_(" Checksum 0x%04x"), csum); 198 if (csum != exp_csum) 199 printf(_(" (EXPECTED 0x%04x)"), exp_csum); 200 printf(_(", unused inodes %u\n"), 201 ext2fs_bg_itable_unused(fs, i)); 202 } 203 has_super = ((i==0) || super_blk); 204 if (has_super) { 205 printf (_(" %s superblock at "), 206 i == 0 ? _("Primary") : _("Backup")); 207 print_number(super_blk); 208 } 209 if (old_desc_blk) { 210 printf(_(", Group descriptors at ")); 211 print_range(old_desc_blk, 212 old_desc_blk + old_desc_blocks - 1); 213 if (reserved_gdt) { 214 printf(_("\n Reserved GDT blocks at ")); 215 print_range(old_desc_blk + old_desc_blocks, 216 old_desc_blk + old_desc_blocks + 217 reserved_gdt - 1); 218 } 219 } else if (new_desc_blk) { 220 fputc(has_super ? ',' : ' ', stdout); 221 printf(_(" Group descriptor at ")); 222 print_number(new_desc_blk); 223 has_super++; 224 } 225 if (has_super) 226 fputc('\n', stdout); 227 fputs(_(" Block bitmap at "), stdout); 228 print_number(ext2fs_block_bitmap_loc(fs, i)); 229 print_bg_rel_offset(fs, ext2fs_block_bitmap_loc(fs, i), 0, 230 first_block, last_block); 231 fputs(_(", Inode bitmap at "), stdout); 232 print_number(ext2fs_inode_bitmap_loc(fs, i)); 233 print_bg_rel_offset(fs, ext2fs_inode_bitmap_loc(fs, i), 0, 234 first_block, last_block); 235 fputs(_("\n Inode table at "), stdout); 236 print_range(ext2fs_inode_table_loc(fs, i), 237 ext2fs_inode_table_loc(fs, i) + 238 inode_blocks_per_group - 1); 239 print_bg_rel_offset(fs, ext2fs_inode_table_loc(fs, i), 1, 240 first_block, last_block); 241 printf (_("\n %u free %s, %u free inodes, " 242 "%u directories%s"), 243 ext2fs_bg_free_blocks_count(fs, i), units, 244 ext2fs_bg_free_inodes_count(fs, i), 245 ext2fs_bg_used_dirs_count(fs, i), 246 ext2fs_bg_itable_unused(fs, i) ? "" : "\n"); 247 if (ext2fs_bg_itable_unused(fs, i)) 248 printf (_(", %u unused inodes\n"), 249 ext2fs_bg_itable_unused(fs, i)); 250 if (block_bitmap) { 251 fputs(_(" Free blocks: "), stdout); 252 ext2fs_get_block_bitmap_range2(fs->block_map, 253 blk_itr, block_nbytes << 3, block_bitmap); 254 print_free(i, block_bitmap, 255 fs->super->s_clusters_per_group, 256 fs->super->s_first_data_block, 257 EXT2FS_CLUSTER_RATIO(fs)); 258 fputc('\n', stdout); 259 blk_itr += fs->super->s_clusters_per_group; 260 } 261 if (inode_bitmap) { 262 fputs(_(" Free inodes: "), stdout); 263 ext2fs_get_inode_bitmap_range2(fs->inode_map, 264 ino_itr, inode_nbytes << 3, inode_bitmap); 265 print_free(i, inode_bitmap, 266 fs->super->s_inodes_per_group, 1, 1); 267 fputc('\n', stdout); 268 ino_itr += fs->super->s_inodes_per_group; 269 } 270 } 271 if (block_bitmap) 272 free(block_bitmap); 273 if (inode_bitmap) 274 free(inode_bitmap); 275} 276 277static void list_bad_blocks(ext2_filsys fs, int dump) 278{ 279 badblocks_list bb_list = 0; 280 badblocks_iterate bb_iter; 281 blk_t blk; 282 errcode_t retval; 283 const char *header, *fmt; 284 285 retval = ext2fs_read_bb_inode(fs, &bb_list); 286 if (retval) { 287 com_err("ext2fs_read_bb_inode", retval, 0); 288 return; 289 } 290 retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); 291 if (retval) { 292 com_err("ext2fs_badblocks_list_iterate_begin", retval, 293 _("while printing bad block list")); 294 return; 295 } 296 if (dump) { 297 header = fmt = "%u\n"; 298 } else { 299 header = _("Bad blocks: %u"); 300 fmt = ", %u"; 301 } 302 while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) { 303 printf(header ? header : fmt, blk); 304 header = 0; 305 } 306 ext2fs_badblocks_list_iterate_end(bb_iter); 307 if (!dump) 308 fputc('\n', stdout); 309 ext2fs_badblocks_list_free(bb_list); 310} 311 312static void print_inline_journal_information(ext2_filsys fs) 313{ 314 journal_superblock_t *jsb; 315 struct ext2_inode inode; 316 ext2_file_t journal_file; 317 errcode_t retval; 318 ino_t ino = fs->super->s_journal_inum; 319 char buf[1024]; 320 __u32 *mask_ptr, mask, m; 321 int i, j, size, printed = 0; 322 323 retval = ext2fs_read_inode(fs, ino, &inode); 324 if (retval) { 325 com_err(program_name, retval, 326 _("while reading journal inode")); 327 exit(1); 328 } 329 retval = ext2fs_file_open2(fs, ino, &inode, 0, &journal_file); 330 if (retval) { 331 com_err(program_name, retval, 332 _("while opening journal inode")); 333 exit(1); 334 } 335 retval = ext2fs_file_read(journal_file, buf, sizeof(buf), 0); 336 if (retval) { 337 com_err(program_name, retval, 338 _("while reading journal super block")); 339 exit(1); 340 } 341 ext2fs_file_close(journal_file); 342 jsb = (journal_superblock_t *) buf; 343 if (be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) { 344 fprintf(stderr, 345 "Journal superblock magic number invalid!\n"); 346 exit(1); 347 } 348 printf(_("Journal features: ")); 349 for (i=0, mask_ptr=&jsb->s_feature_compat; i <3; i++,mask_ptr++) { 350 mask = be32_to_cpu(*mask_ptr); 351 for (j=0,m=1; j < 32; j++, m<<=1) { 352 if (mask & m) { 353 printf(" %s", e2p_jrnl_feature2string(i, m)); 354 printed++; 355 } 356 } 357 } 358 if (printed == 0) 359 printf(" (none)"); 360 printf("\n"); 361 fputs(_("Journal size: "), stdout); 362 if ((fs->super->s_feature_ro_compat & 363 EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && 364 (inode.i_flags & EXT4_HUGE_FILE_FL)) 365 size = inode.i_blocks / (fs->blocksize / 1024); 366 else 367 size = inode.i_blocks >> 1; 368 if (size < 8192) 369 printf("%uk\n", size); 370 else 371 printf("%uM\n", size >> 10); 372 printf(_("Journal length: %u\n" 373 "Journal sequence: 0x%08x\n" 374 "Journal start: %u\n"), 375 (unsigned int)ntohl(jsb->s_maxlen), 376 (unsigned int)ntohl(jsb->s_sequence), 377 (unsigned int)ntohl(jsb->s_start)); 378} 379 380static void print_journal_information(ext2_filsys fs) 381{ 382 errcode_t retval; 383 char buf[1024]; 384 char str[80]; 385 unsigned int i; 386 journal_superblock_t *jsb; 387 388 /* Get the journal superblock */ 389 if ((retval = io_channel_read_blk64(fs->io, fs->super->s_first_data_block+1, -1024, buf))) { 390 com_err(program_name, retval, 391 _("while reading journal superblock")); 392 exit(1); 393 } 394 jsb = (journal_superblock_t *) buf; 395 if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || 396 (jsb->s_header.h_blocktype != 397 (unsigned) ntohl(JFS_SUPERBLOCK_V2))) { 398 com_err(program_name, 0, 399 _("Couldn't find journal superblock magic numbers")); 400 exit(1); 401 } 402 403 printf(_("\nJournal block size: %u\n" 404 "Journal length: %u\n" 405 "Journal first block: %u\n" 406 "Journal sequence: 0x%08x\n" 407 "Journal start: %u\n" 408 "Journal number of users: %u\n"), 409 (unsigned int)ntohl(jsb->s_blocksize), (unsigned int)ntohl(jsb->s_maxlen), 410 (unsigned int)ntohl(jsb->s_first), (unsigned int)ntohl(jsb->s_sequence), 411 (unsigned int)ntohl(jsb->s_start), (unsigned int)ntohl(jsb->s_nr_users)); 412 413 for (i=0; i < ntohl(jsb->s_nr_users); i++) { 414 uuid_unparse(&jsb->s_users[i*16], str); 415 printf(i ? " %s\n" 416 : _("Journal users: %s\n"), 417 str); 418 } 419} 420 421static void parse_extended_opts(const char *opts, blk64_t *superblock, 422 int *blocksize) 423{ 424 char *buf, *token, *next, *p, *arg, *badopt = 0; 425 int len; 426 int do_usage = 0; 427 428 len = strlen(opts); 429 buf = malloc(len+1); 430 if (!buf) { 431 fprintf(stderr, 432 _("Couldn't allocate memory to parse options!\n")); 433 exit(1); 434 } 435 strcpy(buf, opts); 436 for (token = buf; token && *token; token = next) { 437 p = strchr(token, ','); 438 next = 0; 439 if (p) { 440 *p = 0; 441 next = p+1; 442 } 443 arg = strchr(token, '='); 444 if (arg) { 445 *arg = 0; 446 arg++; 447 } 448 if (strcmp(token, "superblock") == 0 || 449 strcmp(token, "sb") == 0) { 450 if (!arg) { 451 do_usage++; 452 badopt = token; 453 continue; 454 } 455 *superblock = strtoul(arg, &p, 0); 456 if (*p) { 457 fprintf(stderr, 458 _("Invalid superblock parameter: %s\n"), 459 arg); 460 do_usage++; 461 continue; 462 } 463 } else if (strcmp(token, "blocksize") == 0 || 464 strcmp(token, "bs") == 0) { 465 if (!arg) { 466 do_usage++; 467 badopt = token; 468 continue; 469 } 470 *blocksize = strtoul(arg, &p, 0); 471 if (*p) { 472 fprintf(stderr, 473 _("Invalid blocksize parameter: %s\n"), 474 arg); 475 do_usage++; 476 continue; 477 } 478 } else { 479 do_usage++; 480 badopt = token; 481 } 482 } 483 if (do_usage) { 484 fprintf(stderr, _("\nBad extended option(s) specified: %s\n\n" 485 "Extended options are separated by commas, " 486 "and may take an argument which\n" 487 "\tis set off by an equals ('=') sign.\n\n" 488 "Valid extended options are:\n" 489 "\tsuperblock=<superblock number>\n" 490 "\tblocksize=<blocksize>\n"), 491 badopt ? badopt : ""); 492 free(buf); 493 exit(1); 494 } 495 free(buf); 496} 497 498int main (int argc, char ** argv) 499{ 500 errcode_t retval; 501 ext2_filsys fs; 502 int print_badblocks = 0; 503 blk64_t use_superblock = 0; 504 int use_blocksize = 0; 505 int image_dump = 0; 506 int force = 0; 507 int flags; 508 int header_only = 0; 509 int c; 510 511#ifdef ENABLE_NLS 512 setlocale(LC_MESSAGES, ""); 513 setlocale(LC_CTYPE, ""); 514 bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 515 textdomain(NLS_CAT_NAME); 516 set_com_err_gettext(gettext); 517#endif 518 add_error_table(&et_ext2_error_table); 519 fprintf (stderr, "dumpe2fs %s (%s)\n", E2FSPROGS_VERSION, 520 E2FSPROGS_DATE); 521 if (argc && *argv) 522 program_name = *argv; 523 524 while ((c = getopt (argc, argv, "bfhixVo:")) != EOF) { 525 switch (c) { 526 case 'b': 527 print_badblocks++; 528 break; 529 case 'f': 530 force++; 531 break; 532 case 'h': 533 header_only++; 534 break; 535 case 'i': 536 image_dump++; 537 break; 538 case 'o': 539 parse_extended_opts(optarg, &use_superblock, 540 &use_blocksize); 541 break; 542 case 'V': 543 /* Print version number and exit */ 544 fprintf(stderr, _("\tUsing %s\n"), 545 error_message(EXT2_ET_BASE)); 546 exit(0); 547 case 'x': 548 hex_format++; 549 break; 550 default: 551 usage(); 552 } 553 } 554 if (optind > argc - 1) 555 usage(); 556 device_name = argv[optind++]; 557 flags = EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS; 558 if (force) 559 flags |= EXT2_FLAG_FORCE; 560 if (image_dump) 561 flags |= EXT2_FLAG_IMAGE_FILE; 562 563 if (use_superblock && !use_blocksize) { 564 for (use_blocksize = EXT2_MIN_BLOCK_SIZE; 565 use_blocksize <= EXT2_MAX_BLOCK_SIZE; 566 use_blocksize *= 2) { 567 retval = ext2fs_open (device_name, flags, 568 use_superblock, 569 use_blocksize, unix_io_manager, 570 &fs); 571 if (!retval) 572 break; 573 } 574 } else 575 retval = ext2fs_open (device_name, flags, use_superblock, 576 use_blocksize, unix_io_manager, &fs); 577 if (retval) { 578 com_err (program_name, retval, _("while trying to open %s"), 579 device_name); 580 printf (_("Couldn't find valid filesystem superblock.\n")); 581 exit (1); 582 } 583 fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE; 584 if (print_badblocks) { 585 list_bad_blocks(fs, 1); 586 } else { 587 list_super (fs->super); 588 if (fs->super->s_feature_incompat & 589 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { 590 print_journal_information(fs); 591 ext2fs_close(fs); 592 exit(0); 593 } 594 if ((fs->super->s_feature_compat & 595 EXT3_FEATURE_COMPAT_HAS_JOURNAL) && 596 (fs->super->s_journal_inum != 0)) 597 print_inline_journal_information(fs); 598 list_bad_blocks(fs, 0); 599 if (header_only) { 600 ext2fs_close (fs); 601 exit (0); 602 } 603 retval = ext2fs_read_bitmaps (fs); 604 list_desc (fs); 605 if (retval) { 606 printf(_("\n%s: %s: error reading bitmaps: %s\n"), 607 program_name, device_name, 608 error_message(retval)); 609 } 610 } 611 ext2fs_close (fs); 612 remove_error_table(&et_ext2_error_table); 613 exit (0); 614} 615