debugfs.c revision b044c2e02af46c54206f0f6e29896ab32681a7db
1/* 2 * debugfs.c --- a program which allows you to attach an ext2fs 3 * filesystem and play with it. 4 * 5 * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed 6 * under the terms of the GNU Public License. 7 * 8 * Modifications by Robert Sanders <gt8134b@prism.gatech.edu> 9 */ 10 11#include <stdio.h> 12#include <unistd.h> 13#include <stdlib.h> 14#include <ctype.h> 15#include <string.h> 16#include <time.h> 17#ifdef HAVE_GETOPT_H 18#include <getopt.h> 19#else 20extern int optind; 21extern char *optarg; 22#endif 23#ifdef HAVE_OPTRESET 24extern int optreset; /* defined by BSD, but not others */ 25#endif 26#ifdef HAVE_ERRNO_H 27#include <errno.h> 28#endif 29#include <fcntl.h> 30#include <sys/types.h> 31#include <sys/stat.h> 32 33#include "et/com_err.h" 34#include "ss/ss.h" 35#include "debugfs.h" 36#include "uuid/uuid.h" 37#include "e2p/e2p.h" 38 39#include "../version.h" 40 41extern ss_request_table debug_cmds; 42 43ext2_filsys current_fs = NULL; 44ext2_ino_t root, cwd; 45 46static void open_filesystem(char *device, int open_flags, blk_t superblock, 47 blk_t blocksize, int catastrophic) 48{ 49 int retval; 50 51 if (superblock != 0 && blocksize == 0) { 52 com_err(device, 0, "if you specify the superblock, you must also specify the block size"); 53 current_fs = NULL; 54 return; 55 } 56 57 if (catastrophic && (open_flags & EXT2_FLAG_RW)) { 58 com_err(device, 0, 59 "opening read-only because of catastrophic mode"); 60 open_flags &= ~EXT2_FLAG_RW; 61 } 62 63 retval = ext2fs_open(device, open_flags, superblock, blocksize, 64 unix_io_manager, ¤t_fs); 65 if (retval) { 66 com_err(device, retval, "while opening filesystem"); 67 current_fs = NULL; 68 return; 69 } 70 71 if (catastrophic) 72 com_err(device, 0, "catastrophic mode - not reading inode or group bitmaps"); 73 else { 74 retval = ext2fs_read_inode_bitmap(current_fs); 75 if (retval) { 76 com_err(device, retval, "while reading inode bitmap"); 77 goto errout; 78 } 79 retval = ext2fs_read_block_bitmap(current_fs); 80 if (retval) { 81 com_err(device, retval, "while reading block bitmap"); 82 goto errout; 83 } 84 } 85 root = cwd = EXT2_ROOT_INO; 86 return; 87 88errout: 89 retval = ext2fs_close(current_fs); 90 if (retval) 91 com_err(device, retval, "while trying to close filesystem"); 92 current_fs = NULL; 93} 94 95void do_open_filesys(int argc, char **argv) 96{ 97 const char *usage = "Usage: open [-s superblock] [-b blocksize] [-c] [-w] <device>"; 98 int c; 99 int catastrophic = 0; 100 blk_t superblock = 0; 101 blk_t blocksize = 0; 102 char *tmp; 103 int open_flags = 0; 104 105 optind = 0; 106#ifdef HAVE_OPTRESET 107 optreset = 1; /* Makes BSD getopt happy */ 108#endif 109 while ((c = getopt (argc, argv, "wfcb:s:")) != EOF) { 110 switch (c) { 111 case 'w': 112 open_flags |= EXT2_FLAG_RW; 113 break; 114 case 'f': 115 open_flags |= EXT2_FLAG_FORCE; 116 break; 117 case 'c': 118 catastrophic = 1; 119 break; 120 case 'b': 121 blocksize = strtoul(optarg, &tmp, 0); 122 if (*tmp) { 123 com_err(argv[0], 0, 124 "Bad block size - %s", optarg); 125 return; 126 } 127 break; 128 case 's': 129 superblock = strtoul(optarg, &tmp, 0); 130 if (*tmp) { 131 com_err(argv[0], 0, 132 "Bad superblock number - %s", optarg); 133 return; 134 } 135 break; 136 default: 137 com_err(argv[0], 0, usage); 138 return; 139 } 140 } 141 if (optind != argc-1) { 142 com_err(argv[0], 0, usage); 143 return; 144 } 145 if (check_fs_not_open(argv[0])) 146 return; 147 open_filesystem(argv[optind], open_flags, 148 superblock, blocksize, catastrophic); 149} 150 151void do_lcd(int argc, char **argv) 152{ 153 const char *usage = "Usage: lcd <native dir>"; 154 155 if (argc != 2) { 156 com_err(argv[0], 0, usage); 157 return; 158 } 159 160 if (chdir(argv[1]) == -1) { 161 com_err(argv[0], errno, 162 "while trying to change native directory to %s", 163 argv[1]); 164 return; 165 } 166} 167 168static void close_filesystem(NOARGS) 169{ 170 int retval; 171 172 if (current_fs->flags & EXT2_FLAG_IB_DIRTY) { 173 retval = ext2fs_write_inode_bitmap(current_fs); 174 if (retval) 175 com_err("ext2fs_write_inode_bitmap", retval, ""); 176 } 177 if (current_fs->flags & EXT2_FLAG_BB_DIRTY) { 178 retval = ext2fs_write_block_bitmap(current_fs); 179 if (retval) 180 com_err("ext2fs_write_block_bitmap", retval, ""); 181 } 182 retval = ext2fs_close(current_fs); 183 if (retval) 184 com_err("ext2fs_close", retval, ""); 185 current_fs = NULL; 186 return; 187} 188 189void do_close_filesys(int argc, char **argv) 190{ 191 if (argc > 1) { 192 com_err(argv[0], 0, "Usage: close_filesys"); 193 return; 194 } 195 if (check_fs_open(argv[0])) 196 return; 197 close_filesystem(); 198} 199 200void do_init_filesys(int argc, char **argv) 201{ 202 const char *usage = "Usage: initialize <device> <blocksize>"; 203 struct ext2_super_block param; 204 errcode_t retval; 205 char *tmp; 206 207 if (argc != 3) { 208 com_err(argv[0], 0, usage); 209 return; 210 } 211 if (check_fs_not_open(argv[0])) 212 return; 213 214 memset(¶m, 0, sizeof(struct ext2_super_block)); 215 param.s_blocks_count = strtoul(argv[2], &tmp, 0); 216 if (*tmp) { 217 com_err(argv[0], 0, "Bad blocks count - %s", argv[2]); 218 return; 219 } 220 retval = ext2fs_initialize(argv[1], 0, ¶m, 221 unix_io_manager, ¤t_fs); 222 if (retval) { 223 com_err(argv[1], retval, "while initializing filesystem"); 224 current_fs = NULL; 225 return; 226 } 227 root = cwd = EXT2_ROOT_INO; 228 return; 229} 230 231static void print_features(struct ext2_super_block * s, FILE *f) 232{ 233 int i, j, printed=0; 234__u32 *mask = &s->s_feature_compat, m; 235 236 printf ("Filesystem features:"); 237 for (i=0; i <3; i++,mask++) { 238 for (j=0,m=1; j < 32; j++, m<<=1) { 239 if (*mask & m) { 240 fprintf(f, " %s", e2p_feature2string(i, m)); 241 printed++; 242 } 243 } 244 } 245 if (printed == 0) 246 printf("(none)"); 247 printf("\n"); 248} 249 250void do_show_super_stats(int argc, char *argv[]) 251{ 252 int i; 253 FILE *out; 254 struct ext2_group_desc *gdp; 255 int c, header_only = 0; 256 const char *usage = "Usage: show_super [-h]"; 257 258 optind = 0; 259#ifdef HAVE_OPTRESET 260 optreset = 1; /* Makes BSD getopt happy */ 261#endif 262 while ((c = getopt (argc, argv, "h")) != EOF) { 263 switch (c) { 264 case 'h': 265 header_only++; 266 break; 267 default: 268 com_err(argv[0], 0, usage); 269 return; 270 } 271 } 272 if (optind != argc) { 273 com_err(argv[0], 0, usage); 274 return; 275 } 276 if (check_fs_open(argv[0])) 277 return; 278 out = open_pager(); 279 280 list_super2(current_fs->super, out); 281 282 if (header_only) { 283 close_pager(out); 284 return; 285 } 286 287 gdp = ¤t_fs->group_desc[0]; 288 for (i = 0; i < current_fs->group_desc_count; i++, gdp++) 289 fprintf(out, " Group %2d: block bitmap at %d, " 290 "inode bitmap at %d, " 291 "inode table at %d\n" 292 " %d free block%s, " 293 "%d free inode%s, " 294 "%d used director%s\n", 295 i, gdp->bg_block_bitmap, 296 gdp->bg_inode_bitmap, gdp->bg_inode_table, 297 gdp->bg_free_blocks_count, 298 gdp->bg_free_blocks_count != 1 ? "s" : "", 299 gdp->bg_free_inodes_count, 300 gdp->bg_free_inodes_count != 1 ? "s" : "", 301 gdp->bg_used_dirs_count, 302 gdp->bg_used_dirs_count != 1 ? "ies" : "y"); 303 close_pager(out); 304} 305 306void do_dirty_filesys(int argc, char **argv) 307{ 308 if (check_fs_open(argv[0])) 309 return; 310 if (check_fs_read_write(argv[0])) 311 return; 312 313 if (argv[1] && !strcmp(argv[1], "-clean")) 314 current_fs->super->s_state |= EXT2_VALID_FS; 315 else 316 current_fs->super->s_state &= ~EXT2_VALID_FS; 317 ext2fs_mark_super_dirty(current_fs); 318} 319 320struct list_blocks_struct { 321 FILE *f; 322 int total; 323 blk_t first_block, last_block; 324 int first_bcnt, last_bcnt; 325 int first; 326}; 327 328static void finish_range(struct list_blocks_struct *lb) 329{ 330 if (lb->first_block == 0) 331 return; 332 if (lb->first) 333 lb->first = 0; 334 else 335 fprintf(lb->f, ", "); 336 if (lb->first_block == lb->last_block) 337 fprintf(lb->f, "(%d):%d", lb->first_bcnt, lb->first_block); 338 else 339 fprintf(lb->f, "(%d-%d):%d-%d", lb->first_bcnt, 340 lb->last_bcnt, lb->first_block, lb->last_block); 341 lb->first_block = 0; 342} 343 344static int list_blocks_proc(ext2_filsys fs, blk_t *blocknr, int blockcnt, 345 void *private) 346{ 347 struct list_blocks_struct *lb = (struct list_blocks_struct *) private; 348 349 lb->total++; 350 if (blockcnt >= 0) { 351 /* 352 * See if we can add on to the existing range (if it exists) 353 */ 354 if (lb->first_block && 355 (lb->last_block+1 == *blocknr) && 356 (lb->last_bcnt+1 == blockcnt)) { 357 lb->last_block = *blocknr; 358 lb->last_bcnt = blockcnt; 359 return 0; 360 } 361 /* 362 * Start a new range. 363 */ 364 finish_range(lb); 365 lb->first_block = lb->last_block = *blocknr; 366 lb->first_bcnt = lb->last_bcnt = blockcnt; 367 return 0; 368 } 369 /* 370 * Not a normal block. Always force a new range. 371 */ 372 finish_range(lb); 373 if (lb->first) 374 lb->first = 0; 375 else 376 fprintf(lb->f, ", "); 377 if (blockcnt == -1) 378 fprintf(lb->f, "(IND):%d", *blocknr); 379 else if (blockcnt == -2) 380 fprintf(lb->f, "(DIND):%d", *blocknr); 381 else if (blockcnt == -3) 382 fprintf(lb->f, "(TIND):%d", *blocknr); 383 return 0; 384} 385 386 387static void dump_blocks(FILE *f, ext2_ino_t inode) 388{ 389 struct list_blocks_struct lb; 390 391 fprintf(f, "BLOCKS:\n"); 392 lb.total = 0; 393 lb.first_block = 0; 394 lb.f = f; 395 lb.first = 1; 396 ext2fs_block_iterate(current_fs, inode, 0, NULL, 397 list_blocks_proc, (void *)&lb); 398 finish_range(&lb); 399 if (lb.total) 400 fprintf(f, "\nTOTAL: %d\n", lb.total); 401 fprintf(f,"\n"); 402} 403 404 405static void dump_inode(ext2_ino_t inode_num, struct ext2_inode inode) 406{ 407 const char *i_type; 408 FILE *out; 409 char frag, fsize; 410 int os = current_fs->super->s_creator_os; 411 412 out = open_pager(); 413 if (LINUX_S_ISDIR(inode.i_mode)) i_type = "directory"; 414 else if (LINUX_S_ISREG(inode.i_mode)) i_type = "regular"; 415 else if (LINUX_S_ISLNK(inode.i_mode)) i_type = "symlink"; 416 else if (LINUX_S_ISBLK(inode.i_mode)) i_type = "block special"; 417 else if (LINUX_S_ISCHR(inode.i_mode)) i_type = "character special"; 418 else if (LINUX_S_ISFIFO(inode.i_mode)) i_type = "FIFO"; 419 else if (LINUX_S_ISSOCK(inode.i_mode)) i_type = "socket"; 420 else i_type = "bad type"; 421 fprintf(out, "Inode: %u Type: %s ", inode_num, i_type); 422 fprintf(out, "Mode: %04o Flags: 0x%x Generation: %u\n", 423 inode.i_mode & 0777, inode.i_flags, inode.i_generation); 424 fprintf(out, "User: %5d Group: %5d Size: ", 425 inode.i_uid, inode.i_gid); 426 if (LINUX_S_ISDIR(inode.i_mode)) 427 fprintf(out, "%d\n", inode.i_size); 428 else { 429 __u64 i_size = (inode.i_size | 430 ((unsigned long long)inode.i_size_high << 32)); 431 432 fprintf(out, "%lld\n", i_size); 433 } 434 if (current_fs->super->s_creator_os == EXT2_OS_HURD) 435 fprintf(out, 436 "File ACL: %d Directory ACL: %d Translator: %d\n", 437 inode.i_file_acl, LINUX_S_ISDIR(inode.i_mode) ? inode.i_dir_acl : 0, 438 inode.osd1.hurd1.h_i_translator); 439 else 440 fprintf(out, "File ACL: %d Directory ACL: %d\n", 441 inode.i_file_acl, LINUX_S_ISDIR(inode.i_mode) ? inode.i_dir_acl : 0); 442 fprintf(out, "Links: %d Blockcount: %d\n", inode.i_links_count, 443 inode.i_blocks); 444 switch (os) { 445 case EXT2_OS_LINUX: 446 frag = inode.osd2.linux2.l_i_frag; 447 fsize = inode.osd2.linux2.l_i_fsize; 448 break; 449 case EXT2_OS_HURD: 450 frag = inode.osd2.hurd2.h_i_frag; 451 fsize = inode.osd2.hurd2.h_i_fsize; 452 break; 453 case EXT2_OS_MASIX: 454 frag = inode.osd2.masix2.m_i_frag; 455 fsize = inode.osd2.masix2.m_i_fsize; 456 break; 457 default: 458 frag = fsize = 0; 459 } 460 fprintf(out, "Fragment: Address: %d Number: %d Size: %d\n", 461 inode.i_faddr, frag, fsize); 462 fprintf(out, "ctime: 0x%08x -- %s", inode.i_ctime, 463 time_to_string(inode.i_ctime)); 464 fprintf(out, "atime: 0x%08x -- %s", inode.i_atime, 465 time_to_string(inode.i_atime)); 466 fprintf(out, "mtime: 0x%08x -- %s", inode.i_mtime, 467 time_to_string(inode.i_mtime)); 468 if (inode.i_dtime) 469 fprintf(out, "dtime: 0x%08x -- %s", inode.i_dtime, 470 time_to_string(inode.i_dtime)); 471 if (LINUX_S_ISLNK(inode.i_mode) && inode.i_blocks == 0) 472 fprintf(out, "Fast_link_dest: %.*s\n", 473 inode.i_size, (char *)inode.i_block); 474 else 475 dump_blocks(out, inode_num); 476 close_pager(out); 477} 478 479 480void do_stat(int argc, char *argv[]) 481{ 482 ext2_ino_t inode; 483 struct ext2_inode inode_buf; 484 int retval; 485 486 if (argc != 2) { 487 com_err(argv[0], 0, "Usage: stat <file>"); 488 return; 489 } 490 if (check_fs_open(argv[0])) 491 return; 492 inode = string_to_inode(argv[1]); 493 if (!inode) 494 return; 495 496 retval = ext2fs_read_inode(current_fs, inode, &inode_buf); 497 if (retval) 498 { 499 com_err(argv[0], retval, "while trying to read inode %d", inode); 500 return; 501 } 502 503 dump_inode(inode,inode_buf); 504 return; 505} 506 507void do_chroot(int argc, char *argv[]) 508{ 509 ext2_ino_t inode; 510 int retval; 511 512 if (argc != 2) { 513 com_err(argv[0], 0, "Usage: chroot <file>"); 514 return; 515 } 516 if (check_fs_open(argv[0])) 517 return; 518 inode = string_to_inode(argv[1]); 519 if (!inode) 520 return; 521 522 retval = ext2fs_check_directory(current_fs, inode); 523 if (retval) { 524 com_err(argv[1], retval, ""); 525 return; 526 } 527 root = inode; 528} 529 530void do_clri(int argc, char *argv[]) 531{ 532 ext2_ino_t inode; 533 int retval; 534 struct ext2_inode inode_buf; 535 536 if (argc != 2) { 537 com_err(argv[0], 0, "Usage: clri <file>"); 538 return; 539 } 540 if (check_fs_open(argv[0])) 541 return; 542 if (check_fs_read_write(argv[0])) 543 return; 544 inode = string_to_inode(argv[1]); 545 if (!inode) 546 return; 547 548 retval = ext2fs_read_inode(current_fs, inode, &inode_buf); 549 if (retval) { 550 com_err(argv[0], retval, "while trying to read inode %d", 551 inode); 552 return; 553 } 554 memset(&inode_buf, 0, sizeof(inode_buf)); 555 retval = ext2fs_write_inode(current_fs, inode, &inode_buf); 556 if (retval) { 557 com_err(argv[0], retval, "while trying to write inode %d", 558 inode); 559 return; 560 } 561} 562 563void do_freei(int argc, char *argv[]) 564{ 565 ext2_ino_t inode; 566 567 if (argc != 2) { 568 com_err(argv[0], 0, "Usage: freei <file>"); 569 return; 570 } 571 if (check_fs_open(argv[0])) 572 return; 573 if (check_fs_read_write(argv[0])) 574 return; 575 inode = string_to_inode(argv[1]); 576 if (!inode) 577 return; 578 579 if (!ext2fs_test_inode_bitmap(current_fs->inode_map,inode)) 580 com_err(argv[0], 0, "Warning: inode already clear"); 581 ext2fs_unmark_inode_bitmap(current_fs->inode_map,inode); 582 ext2fs_mark_ib_dirty(current_fs); 583} 584 585void do_seti(int argc, char *argv[]) 586{ 587 ext2_ino_t inode; 588 589 if (argc != 2) { 590 com_err(argv[0], 0, "Usage: seti <file>"); 591 return; 592 } 593 if (check_fs_open(argv[0])) 594 return; 595 if (check_fs_read_write(argv[0])) 596 return; 597 inode = string_to_inode(argv[1]); 598 if (!inode) 599 return; 600 601 if (ext2fs_test_inode_bitmap(current_fs->inode_map,inode)) 602 com_err(argv[0], 0, "Warning: inode already set"); 603 ext2fs_mark_inode_bitmap(current_fs->inode_map,inode); 604 ext2fs_mark_ib_dirty(current_fs); 605} 606 607void do_testi(int argc, char *argv[]) 608{ 609 ext2_ino_t inode; 610 611 if (argc != 2) { 612 com_err(argv[0], 0, "Usage: testi <file>"); 613 return; 614 } 615 if (check_fs_open(argv[0])) 616 return; 617 if (check_fs_bitmaps(argv[0])) 618 return; 619 inode = string_to_inode(argv[1]); 620 if (!inode) 621 return; 622 623 if (ext2fs_test_inode_bitmap(current_fs->inode_map,inode)) 624 printf("Inode %u is marked in use\n", inode); 625 else 626 printf("Inode %u is not in use\n", inode); 627} 628 629 630void do_freeb(int argc, char *argv[]) 631{ 632 blk_t block; 633 char *tmp; 634 635 if (argc != 2) { 636 com_err(argv[0], 0, "Usage: freeb <block>"); 637 return; 638 } 639 if (check_fs_open(argv[0])) 640 return; 641 if (check_fs_read_write(argv[0])) 642 return; 643 block = strtoul(argv[1], &tmp, 0); 644 if (!block || *tmp) { 645 com_err(argv[0], 0, "No block 0"); 646 return; 647 } 648 if (!ext2fs_test_block_bitmap(current_fs->block_map,block)) 649 com_err(argv[0], 0, "Warning: block already clear"); 650 ext2fs_unmark_block_bitmap(current_fs->block_map,block); 651 ext2fs_mark_bb_dirty(current_fs); 652} 653 654void do_setb(int argc, char *argv[]) 655{ 656 blk_t block; 657 char *tmp; 658 659 if (argc != 2) { 660 com_err(argv[0], 0, "Usage: setb <block>"); 661 return; 662 } 663 if (check_fs_open(argv[0])) 664 return; 665 if (check_fs_read_write(argv[0])) 666 return; 667 block = strtoul(argv[1], &tmp, 0); 668 if (!block || *tmp) { 669 com_err(argv[0], 0, "No block 0"); 670 return; 671 } 672 if (ext2fs_test_block_bitmap(current_fs->block_map,block)) 673 com_err(argv[0], 0, "Warning: block already set"); 674 ext2fs_mark_block_bitmap(current_fs->block_map,block); 675 ext2fs_mark_bb_dirty(current_fs); 676} 677 678void do_testb(int argc, char *argv[]) 679{ 680 blk_t block; 681 char *tmp; 682 683 if (argc != 2) { 684 com_err(argv[0], 0, "Usage: testb <block>"); 685 return; 686 } 687 if (check_fs_open(argv[0])) 688 return; 689 if (check_fs_bitmaps(argv[0])) 690 return; 691 block = strtoul(argv[1], &tmp, 0); 692 if (!block || *tmp) { 693 com_err(argv[0], 0, "No block 0"); 694 return; 695 } 696 if (ext2fs_test_block_bitmap(current_fs->block_map,block)) 697 printf("Block %d marked in use\n", block); 698 else printf("Block %d not in use\n", block); 699} 700 701static void modify_u8(char *com, const char *prompt, 702 const char *format, __u8 *val) 703{ 704 char buf[200]; 705 unsigned long v; 706 char *tmp; 707 708 sprintf(buf, format, *val); 709 printf("%30s [%s] ", prompt, buf); 710 fgets(buf, sizeof(buf), stdin); 711 if (buf[strlen (buf) - 1] == '\n') 712 buf[strlen (buf) - 1] = '\0'; 713 if (!buf[0]) 714 return; 715 v = strtoul(buf, &tmp, 0); 716 if (*tmp) 717 com_err(com, 0, "Bad value - %s", buf); 718 else 719 *val = v; 720} 721 722static void modify_u16(char *com, const char *prompt, 723 const char *format, __u16 *val) 724{ 725 char buf[200]; 726 unsigned long v; 727 char *tmp; 728 729 sprintf(buf, format, *val); 730 printf("%30s [%s] ", prompt, buf); 731 fgets(buf, sizeof(buf), stdin); 732 if (buf[strlen (buf) - 1] == '\n') 733 buf[strlen (buf) - 1] = '\0'; 734 if (!buf[0]) 735 return; 736 v = strtoul(buf, &tmp, 0); 737 if (*tmp) 738 com_err(com, 0, "Bad value - %s", buf); 739 else 740 *val = v; 741} 742 743static void modify_u32(char *com, const char *prompt, 744 const char *format, __u32 *val) 745{ 746 char buf[200]; 747 unsigned long v; 748 char *tmp; 749 750 sprintf(buf, format, *val); 751 printf("%30s [%s] ", prompt, buf); 752 fgets(buf, sizeof(buf), stdin); 753 if (buf[strlen (buf) - 1] == '\n') 754 buf[strlen (buf) - 1] = '\0'; 755 if (!buf[0]) 756 return; 757 v = strtoul(buf, &tmp, 0); 758 if (*tmp) 759 com_err(com, 0, "Bad value - %s", buf); 760 else 761 *val = v; 762} 763 764 765void do_modify_inode(int argc, char *argv[]) 766{ 767 struct ext2_inode inode; 768 ext2_ino_t inode_num; 769 int i; 770 errcode_t retval; 771 unsigned char *frag, *fsize; 772 char buf[80]; 773 int os = current_fs->super->s_creator_os; 774 const char *hex_format = "0x%x"; 775 const char *octal_format = "0%o"; 776 const char *decimal_format = "%d"; 777 778 if (argc != 2) { 779 com_err(argv[0], 0, "Usage: modify_inode <file>"); 780 return; 781 } 782 if (check_fs_open(argv[0])) 783 return; 784 if (check_fs_read_write(argv[0])) 785 return; 786 787 inode_num = string_to_inode(argv[1]); 788 if (!inode_num) 789 return; 790 791 retval = ext2fs_read_inode(current_fs, inode_num, &inode); 792 if (retval) { 793 com_err(argv[1], retval, "while trying to read inode %d", 794 inode_num); 795 return; 796 } 797 798 modify_u16(argv[0], "Mode", octal_format, &inode.i_mode); 799 modify_u16(argv[0], "User ID", decimal_format, &inode.i_uid); 800 modify_u16(argv[0], "Group ID", decimal_format, &inode.i_gid); 801 modify_u32(argv[0], "Size", decimal_format, &inode.i_size); 802 modify_u32(argv[0], "Creation time", decimal_format, &inode.i_ctime); 803 modify_u32(argv[0], "Modification time", decimal_format, &inode.i_mtime); 804 modify_u32(argv[0], "Access time", decimal_format, &inode.i_atime); 805 modify_u32(argv[0], "Deletion time", decimal_format, &inode.i_dtime); 806 modify_u16(argv[0], "Link count", decimal_format, &inode.i_links_count); 807 modify_u32(argv[0], "Block count", decimal_format, &inode.i_blocks); 808 modify_u32(argv[0], "File flags", hex_format, &inode.i_flags); 809 modify_u32(argv[0], "Generation", hex_format, &inode.i_generation); 810#if 0 811 modify_u32(argv[0], "Reserved1", decimal_format, &inode.i_reserved1); 812#endif 813 modify_u32(argv[0], "File acl", decimal_format, &inode.i_file_acl); 814 if (LINUX_S_ISDIR(inode.i_mode)) 815 modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl); 816 else 817 modify_u32(argv[0], "High 32bits of size", decimal_format, &inode.i_size_high); 818 819 if (current_fs->super->s_creator_os == EXT2_OS_HURD) 820 modify_u32(argv[0], "Translator Block", 821 decimal_format, &inode.osd1.hurd1.h_i_translator); 822 823 modify_u32(argv[0], "Fragment address", decimal_format, &inode.i_faddr); 824 switch (os) { 825 case EXT2_OS_LINUX: 826 frag = &inode.osd2.linux2.l_i_frag; 827 fsize = &inode.osd2.linux2.l_i_fsize; 828 break; 829 case EXT2_OS_HURD: 830 frag = &inode.osd2.hurd2.h_i_frag; 831 fsize = &inode.osd2.hurd2.h_i_fsize; 832 break; 833 case EXT2_OS_MASIX: 834 frag = &inode.osd2.masix2.m_i_frag; 835 fsize = &inode.osd2.masix2.m_i_fsize; 836 break; 837 default: 838 frag = fsize = 0; 839 } 840 if (frag) 841 modify_u8(argv[0], "Fragment number", decimal_format, frag); 842 if (fsize) 843 modify_u8(argv[0], "Fragment size", decimal_format, fsize); 844 845 for (i=0; i < EXT2_NDIR_BLOCKS; i++) { 846 sprintf(buf, "Direct Block #%d", i); 847 modify_u32(argv[0], buf, decimal_format, &inode.i_block[i]); 848 } 849 modify_u32(argv[0], "Indirect Block", decimal_format, 850 &inode.i_block[EXT2_IND_BLOCK]); 851 modify_u32(argv[0], "Double Indirect Block", decimal_format, 852 &inode.i_block[EXT2_DIND_BLOCK]); 853 modify_u32(argv[0], "Triple Indirect Block", decimal_format, 854 &inode.i_block[EXT2_TIND_BLOCK]); 855 retval = ext2fs_write_inode(current_fs, inode_num, &inode); 856 if (retval) { 857 com_err(argv[1], retval, "while trying to write inode %d", 858 inode_num); 859 return; 860 } 861} 862 863void do_change_working_dir(int argc, char *argv[]) 864{ 865 ext2_ino_t inode; 866 int retval; 867 868 if (argc != 2) { 869 com_err(argv[0], 0, "Usage: cd <file>"); 870 return; 871 } 872 if (check_fs_open(argv[0])) 873 return; 874 875 inode = string_to_inode(argv[1]); 876 if (!inode) 877 return; 878 879 retval = ext2fs_check_directory(current_fs, inode); 880 if (retval) { 881 com_err(argv[1], retval, ""); 882 return; 883 } 884 cwd = inode; 885 return; 886} 887 888void do_print_working_directory(int argc, char *argv[]) 889{ 890 int retval; 891 char *pathname = NULL; 892 893 if (argc > 1) { 894 com_err(argv[0], 0, "Usage: print_working_directory"); 895 return; 896 } 897 if (check_fs_open(argv[0])) 898 return; 899 900 retval = ext2fs_get_pathname(current_fs, cwd, 0, &pathname); 901 if (retval) { 902 com_err(argv[0], retval, 903 "while trying to get pathname of cwd"); 904 } 905 printf("[pwd] INODE: %6u PATH: %s\n", cwd, pathname); 906 free(pathname); 907 retval = ext2fs_get_pathname(current_fs, root, 0, &pathname); 908 if (retval) { 909 com_err(argv[0], retval, 910 "while trying to get pathname of root"); 911 } 912 printf("[root] INODE: %6u PATH: %s\n", root, pathname); 913 free(pathname); 914 return; 915} 916 917static void make_link(char *sourcename, char *destname) 918{ 919 ext2_ino_t inode; 920 int retval; 921 ext2_ino_t dir; 922 char *dest, *cp, *basename; 923 924 /* 925 * Get the source inode 926 */ 927 inode = string_to_inode(sourcename); 928 if (!inode) 929 return; 930 basename = strrchr(sourcename, '/'); 931 if (basename) 932 basename++; 933 else 934 basename = sourcename; 935 /* 936 * Figure out the destination. First see if it exists and is 937 * a directory. 938 */ 939 if (! (retval=ext2fs_namei(current_fs, root, cwd, destname, &dir))) 940 dest = basename; 941 else { 942 /* 943 * OK, it doesn't exist. See if it is 944 * '<dir>/basename' or 'basename' 945 */ 946 cp = strrchr(destname, '/'); 947 if (cp) { 948 *cp = 0; 949 dir = string_to_inode(destname); 950 if (!dir) 951 return; 952 dest = cp+1; 953 } else { 954 dir = cwd; 955 dest = destname; 956 } 957 } 958 959 retval = ext2fs_link(current_fs, dir, dest, inode, 0); 960 if (retval) 961 com_err("make_link", retval, ""); 962 return; 963} 964 965 966void do_link(int argc, char *argv[]) 967{ 968 if (argc != 3) { 969 com_err(argv[0], 0, "Usage: link <source_file> <dest_name>"); 970 return; 971 } 972 if (check_fs_open(argv[0])) 973 return; 974 975 make_link(argv[1], argv[2]); 976} 977 978static void unlink_file_by_name(char *filename) 979{ 980 int retval; 981 ext2_ino_t dir; 982 char *basename; 983 984 basename = strrchr(filename, '/'); 985 if (basename) { 986 *basename++ = '\0'; 987 dir = string_to_inode(filename); 988 if (!dir) 989 return; 990 } else { 991 dir = cwd; 992 basename = filename; 993 } 994 retval = ext2fs_unlink(current_fs, dir, basename, 0, 0); 995 if (retval) 996 com_err("unlink_file_by_name", retval, ""); 997 return; 998} 999 1000void do_unlink(int argc, char *argv[]) 1001{ 1002 if (argc != 2) { 1003 com_err(argv[0], 0, "Usage: unlink <pathname>"); 1004 return; 1005 } 1006 if (check_fs_open(argv[0])) 1007 return; 1008 1009 unlink_file_by_name(argv[1]); 1010} 1011 1012void do_find_free_block(int argc, char *argv[]) 1013{ 1014 blk_t free_blk, goal; 1015 errcode_t retval; 1016 char *tmp; 1017 1018 if ((argc > 2) || (argc==2 && *argv[1] == '?')) { 1019 com_err(argv[0], 0, "Usage: find_free_block [goal]"); 1020 return; 1021 } 1022 if (check_fs_open(argv[0])) 1023 return; 1024 1025 if (argc > 1) { 1026 goal = strtol(argv[1], &tmp, 0); 1027 if (*tmp) { 1028 com_err(argv[0], 0, "Bad goal - %s", argv[1]); 1029 return; 1030 } 1031 } 1032 else 1033 goal = current_fs->super->s_first_data_block; 1034 1035 retval = ext2fs_new_block(current_fs, goal, 0, &free_blk); 1036 if (retval) 1037 com_err("ext2fs_new_block", retval, ""); 1038 else 1039 printf("Free block found: %d\n", free_blk); 1040 1041} 1042 1043void do_find_free_inode(int argc, char *argv[]) 1044{ 1045 ext2_ino_t free_inode, dir; 1046 int mode; 1047 int retval; 1048 char *tmp; 1049 1050 if (argc > 3 || (argc>1 && *argv[1] == '?')) { 1051 com_err(argv[0], 0, "Usage: find_free_inode [dir] [mode]"); 1052 return; 1053 } 1054 if (check_fs_open(argv[0])) 1055 return; 1056 1057 if (argc > 1) { 1058 dir = strtol(argv[1], &tmp, 0); 1059 if (*tmp) { 1060 com_err(argv[0], 0, "Bad dir - %s", argv[1]); 1061 return; 1062 } 1063 } 1064 else 1065 dir = root; 1066 if (argc > 2) { 1067 mode = strtol(argv[2], &tmp, 0); 1068 if (*tmp) { 1069 com_err(argv[0], 0, "Bad mode - %s", argv[2]); 1070 return; 1071 } 1072 } else 1073 mode = 010755; 1074 1075 retval = ext2fs_new_inode(current_fs, dir, mode, 0, &free_inode); 1076 if (retval) 1077 com_err("ext2fs_new_inode", retval, ""); 1078 else 1079 printf("Free inode found: %u\n", free_inode); 1080} 1081 1082static errcode_t copy_file(int fd, ext2_ino_t newfile) 1083{ 1084 ext2_file_t e2_file; 1085 errcode_t retval; 1086 unsigned int got, written; 1087 char buf[8192]; 1088 char *ptr; 1089 1090 retval = ext2fs_file_open(current_fs, newfile, 1091 EXT2_FILE_WRITE, &e2_file); 1092 if (retval) 1093 return retval; 1094 1095 while (1) { 1096 got = read(fd, buf, sizeof(buf)); 1097 if (got == 0) 1098 break; 1099 if (got < 0) { 1100 retval = errno; 1101 goto fail; 1102 } 1103 ptr = buf; 1104 while (got > 0) { 1105 retval = ext2fs_file_write(e2_file, ptr, 1106 got, &written); 1107 if (retval) 1108 goto fail; 1109 1110 got -= written; 1111 ptr += written; 1112 } 1113 } 1114 retval = ext2fs_file_close(e2_file); 1115 1116 return retval; 1117 1118fail: 1119 (void) ext2fs_file_close(e2_file); 1120 return retval; 1121} 1122 1123 1124void do_write(int argc, char *argv[]) 1125{ 1126 int fd; 1127 struct stat statbuf; 1128 ext2_ino_t newfile; 1129 errcode_t retval; 1130 struct ext2_inode inode; 1131 dgrp_t group; 1132 1133 if (check_fs_open(argv[0])) 1134 return; 1135 if (argc != 3) { 1136 com_err(argv[0], 0, "Usage: write <nativefile> <newfile>"); 1137 return; 1138 } 1139 if (check_fs_read_write(argv[0])) 1140 return; 1141 fd = open(argv[1], O_RDONLY); 1142 if (fd < 0) { 1143 com_err(argv[1], fd, ""); 1144 return; 1145 } 1146 if (fstat(fd, &statbuf) < 0) { 1147 com_err(argv[1], errno, ""); 1148 close(fd); 1149 return; 1150 } 1151 1152 retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); 1153 if (retval) { 1154 com_err(argv[0], retval, ""); 1155 close(fd); 1156 return; 1157 } 1158 group = ext2fs_group_of_ino(current_fs, newfile); 1159 current_fs->group_desc[group].bg_free_inodes_count--; 1160 current_fs->super->s_free_inodes_count--; 1161 ext2fs_mark_super_dirty(current_fs); 1162 printf("Allocated inode: %u\n", newfile); 1163 retval = ext2fs_link(current_fs, cwd, argv[2], newfile, 0); 1164 if (retval) { 1165 com_err(argv[2], retval, ""); 1166 close(fd); 1167 return; 1168 } 1169 if (ext2fs_test_inode_bitmap(current_fs->inode_map,newfile)) 1170 com_err(argv[0], 0, "Warning: inode already set"); 1171 ext2fs_mark_inode_bitmap(current_fs->inode_map,newfile); 1172 ext2fs_mark_ib_dirty(current_fs); 1173 memset(&inode, 0, sizeof(inode)); 1174 inode.i_mode = statbuf.st_mode; 1175 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL); 1176 inode.i_links_count = 1; 1177 inode.i_size = statbuf.st_size; 1178 ext2fs_write_inode(current_fs, newfile, &inode); 1179 retval = ext2fs_write_inode(current_fs, newfile, &inode); 1180 if (retval) { 1181 com_err(argv[0], retval, "while trying to write inode %d", 1182 inode); 1183 close(fd); 1184 return; 1185 } 1186 if (LINUX_S_ISREG(inode.i_mode)) { 1187 retval = copy_file(fd, newfile); 1188 if (retval) 1189 com_err("copy_file", retval, ""); 1190 } 1191 close(fd); 1192} 1193 1194void do_mknod(int argc, char *argv[]) 1195{ 1196 unsigned long mode, major, minor, nr; 1197 ext2_ino_t newfile; 1198 errcode_t retval; 1199 struct ext2_inode inode; 1200 1201 if (check_fs_open(argv[0])) 1202 return; 1203 if (argc < 3 || argv[2][1]) { 1204 com_err(argv[0], 0, "Usage: mknod <name> [p| [c|b] <major> <minor>]"); 1205 return; 1206 } 1207 mode = minor = major = 0; 1208 switch (argv[2][0]) { 1209 case 'p': 1210 mode = LINUX_S_IFIFO; 1211 nr = 3; 1212 break; 1213 case 'c': 1214 mode = LINUX_S_IFCHR; 1215 nr = 5; 1216 break; 1217 case 'b': 1218 mode = LINUX_S_IFBLK; 1219 nr = 5; 1220 break; 1221 default: 1222 nr = 0; 1223 } 1224 if (nr == 5) { 1225 major = strtoul(argv[3], argv+3, 0); 1226 minor = strtoul(argv[4], argv+4, 0); 1227 if (major > 255 || minor > 255 || argv[3][0] || argv[4][0]) 1228 nr = 0; 1229 } 1230 if (argc != nr) { 1231 com_err(argv[0], 0, "Usage: mknod <name> [p| [c|b] <major> <minor>]"); 1232 return; 1233 } 1234 if (check_fs_read_write(argv[0])) 1235 return; 1236 retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); 1237 if (retval) { 1238 com_err(argv[0], retval, ""); 1239 return; 1240 } 1241 printf("Allocated inode: %u\n", newfile); 1242 retval = ext2fs_link(current_fs, cwd, argv[1], newfile, 0); 1243 if (retval) { 1244 if (retval == EXT2_ET_DIR_NO_SPACE) { 1245 retval = ext2fs_expand_dir(current_fs, cwd); 1246 if (!retval) 1247 retval = ext2fs_link(current_fs, cwd, 1248 argv[1], newfile, 0); 1249 } 1250 if (retval) { 1251 com_err(argv[1], retval, ""); 1252 return; 1253 } 1254 } 1255 if (ext2fs_test_inode_bitmap(current_fs->inode_map,newfile)) 1256 com_err(argv[0], 0, "Warning: inode already set"); 1257 ext2fs_mark_inode_bitmap(current_fs->inode_map, newfile); 1258 ext2fs_mark_ib_dirty(current_fs); 1259 memset(&inode, 0, sizeof(inode)); 1260 inode.i_mode = mode; 1261 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL); 1262 inode.i_block[0] = major*256+minor; 1263 inode.i_links_count = 1; 1264 ext2fs_write_inode(current_fs, newfile, &inode); 1265 retval = ext2fs_write_inode(current_fs, newfile, &inode); 1266 if (retval) { 1267 com_err(argv[0], retval, "while trying to write inode %d", inode); 1268 return; 1269 } 1270} 1271 1272void do_mkdir(int argc, char *argv[]) 1273{ 1274 char *cp; 1275 ext2_ino_t parent; 1276 char *name; 1277 errcode_t retval; 1278 1279 if (check_fs_open(argv[0])) 1280 return; 1281 1282 if (argc != 2) { 1283 com_err(argv[0], 0, "Usage: mkdir <file>"); 1284 return; 1285 } 1286 1287 if (check_fs_read_write(argv[0])) 1288 return; 1289 1290 cp = strrchr(argv[1], '/'); 1291 if (cp) { 1292 *cp = 0; 1293 parent = string_to_inode(argv[1]); 1294 if (!parent) { 1295 com_err(argv[1], ENOENT, ""); 1296 return; 1297 } 1298 name = cp+1; 1299 } else { 1300 parent = cwd; 1301 name = argv[1]; 1302 } 1303 1304 1305 retval = ext2fs_mkdir(current_fs, parent, 0, name); 1306 if (retval) { 1307 com_err("ext2fs_mkdir", retval, ""); 1308 return; 1309 } 1310 1311} 1312 1313void do_rmdir(int argc, char *argv[]) 1314{ 1315 printf("Unimplemented\n"); 1316} 1317 1318 1319static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr, 1320 int blockcnt, void *private) 1321{ 1322 printf("%d ", *blocknr); 1323 ext2fs_unmark_block_bitmap(fs->block_map,*blocknr); 1324 return 0; 1325} 1326 1327static void kill_file_by_inode(ext2_ino_t inode) 1328{ 1329 struct ext2_inode inode_buf; 1330 1331 ext2fs_read_inode(current_fs, inode, &inode_buf); 1332 inode_buf.i_dtime = time(NULL); 1333 ext2fs_write_inode(current_fs, inode, &inode_buf); 1334 1335 printf("Kill file by inode %u\n", inode); 1336 ext2fs_block_iterate(current_fs, inode, 0, NULL, 1337 release_blocks_proc, NULL); 1338 printf("\n"); 1339 ext2fs_unmark_inode_bitmap(current_fs->inode_map, inode); 1340 1341 ext2fs_mark_bb_dirty(current_fs); 1342 ext2fs_mark_ib_dirty(current_fs); 1343} 1344 1345 1346void do_kill_file(int argc, char *argv[]) 1347{ 1348 ext2_ino_t inode_num; 1349 1350 if (argc != 2) { 1351 com_err(argv[0], 0, "Usage: kill_file <file>"); 1352 return; 1353 } 1354 if (check_fs_open(argv[0])) 1355 return; 1356 1357 if (check_fs_read_write(argv[0])) 1358 return; 1359 1360 inode_num = string_to_inode(argv[1]); 1361 if (!inode_num) { 1362 com_err(argv[0], 0, "Cannot find file"); 1363 return; 1364 } 1365 kill_file_by_inode(inode_num); 1366} 1367 1368void do_rm(int argc, char *argv[]) 1369{ 1370 int retval; 1371 ext2_ino_t inode_num; 1372 struct ext2_inode inode; 1373 1374 if (argc != 2) { 1375 com_err(argv[0], 0, "Usage: rm <filename>"); 1376 return; 1377 } 1378 if (check_fs_open(argv[0])) 1379 return; 1380 1381 if (check_fs_read_write(argv[0])) 1382 return; 1383 1384 retval = ext2fs_namei(current_fs, root, cwd, argv[1], &inode_num); 1385 if (retval) { 1386 com_err(argv[0], retval, "while trying to resolve filename"); 1387 return; 1388 } 1389 1390 retval = ext2fs_read_inode(current_fs,inode_num,&inode); 1391 if (retval) { 1392 com_err(argv[0], retval, "while reading file's inode"); 1393 return; 1394 } 1395 1396 if (LINUX_S_ISDIR(inode.i_mode)) { 1397 com_err(argv[0], 0, "file is a directory"); 1398 return; 1399 } 1400 1401 --inode.i_links_count; 1402 retval = ext2fs_write_inode(current_fs,inode_num,&inode); 1403 if (retval) { 1404 com_err(argv[0], retval, "while writing inode"); 1405 return; 1406 } 1407 1408 unlink_file_by_name(argv[1]); 1409 if (inode.i_links_count == 0) 1410 kill_file_by_inode(inode_num); 1411} 1412 1413void do_show_debugfs_params(int argc, char *argv[]) 1414{ 1415 FILE *out = stdout; 1416 1417 if (current_fs) 1418 fprintf(out, "Open mode: read-%s\n", 1419 current_fs->flags & EXT2_FLAG_RW ? "write" : "only"); 1420 fprintf(out, "Filesystem in use: %s\n", 1421 current_fs ? current_fs->device_name : "--none--"); 1422} 1423 1424void do_expand_dir(int argc, char *argv[]) 1425{ 1426 ext2_ino_t inode; 1427 int retval; 1428 1429 if (argc != 2) { 1430 com_err(argv[0], 0, "Usage: expand_dir <file>"); 1431 return; 1432 } 1433 if (check_fs_open(argv[0])) 1434 return; 1435 inode = string_to_inode(argv[1]); 1436 if (!inode) 1437 return; 1438 1439 retval = ext2fs_expand_dir(current_fs, inode); 1440 if (retval) 1441 com_err("ext2fs_expand_dir", retval, ""); 1442 return; 1443} 1444 1445void do_features(int argc, char *argv[]) 1446{ 1447 int i; 1448 1449 if (check_fs_open(argv[0])) 1450 return; 1451 1452 if ((argc != 1) && check_fs_read_write(argv[0])) 1453 return; 1454 for (i=1; i < argc; i++) { 1455 if (e2p_edit_feature(argv[i], 1456 ¤t_fs->super->s_feature_compat, 0)) 1457 com_err(argv[0], 0, "Unknown feature: %s\n", 1458 argv[i]); 1459 else 1460 ext2fs_mark_super_dirty(current_fs); 1461 } 1462 print_features(current_fs->super, stdout); 1463} 1464 1465static int source_file(const char *cmd_file, int sci_idx) 1466{ 1467 FILE *f; 1468 char buf[256]; 1469 char *cp; 1470 int exit_status = 0; 1471 int retval; 1472 1473 if (strcmp(cmd_file, "-") == 0) 1474 f = stdin; 1475 else { 1476 f = fopen(cmd_file, "r"); 1477 if (!f) { 1478 perror(cmd_file); 1479 exit(1); 1480 } 1481 } 1482 setbuf(stdout, NULL); 1483 setbuf(stderr, NULL); 1484 while (!feof(f)) { 1485 if (fgets(buf, sizeof(buf), f) == NULL) 1486 break; 1487 cp = strchr(buf, '\n'); 1488 if (cp) 1489 *cp = 0; 1490 cp = strchr(buf, '\r'); 1491 if (cp) 1492 *cp = 0; 1493 printf("debugfs: %s\n", buf); 1494 retval = ss_execute_line(sci_idx, buf); 1495 if (retval) { 1496 ss_perror(sci_idx, retval, buf); 1497 exit_status++; 1498 } 1499 } 1500 return exit_status; 1501} 1502 1503int main(int argc, char **argv) 1504{ 1505 int retval; 1506 int sci_idx; 1507 const char *usage = "Usage: debugfs [-b blocksize] [-s superblock] [-f cmd_file] [-R request] [-V] [[-w] [-c] device]"; 1508 int c; 1509 int open_flags = 0; 1510 char *request = 0; 1511 int exit_status = 0; 1512 char *cmd_file = 0; 1513 blk_t superblock = 0; 1514 blk_t blocksize = 0; 1515 int catastrophic = 0; 1516 char *tmp; 1517 1518 initialize_ext2_error_table(); 1519 fprintf (stderr, "debugfs %s, %s for EXT2 FS %s, %s\n", 1520 E2FSPROGS_VERSION, E2FSPROGS_DATE, 1521 EXT2FS_VERSION, EXT2FS_DATE); 1522 1523 while ((c = getopt (argc, argv, "wcR:f:b:s:V")) != EOF) { 1524 switch (c) { 1525 case 'R': 1526 request = optarg; 1527 break; 1528 case 'f': 1529 cmd_file = optarg; 1530 break; 1531 case 'w': 1532 open_flags = EXT2_FLAG_RW; 1533 break; 1534 case 'b': 1535 blocksize = strtoul(optarg, &tmp, 0); 1536 if (*tmp) { 1537 com_err(argv[0], 0, 1538 "Bad block size - %s", optarg); 1539 return 1; 1540 } 1541 break; 1542 case 's': 1543 superblock = strtoul(optarg, &tmp, 0); 1544 if (*tmp) { 1545 com_err(argv[0], 0, 1546 "Bad superblock number - %s", optarg); 1547 return 1; 1548 } 1549 break; 1550 case 'c': 1551 catastrophic = 1; 1552 break; 1553 case 'V': 1554 /* Print version number and exit */ 1555 fprintf(stderr, "\tUsing %s\n", 1556 error_message(EXT2_ET_BASE)); 1557 exit(0); 1558 default: 1559 com_err(argv[0], 0, usage); 1560 return 1; 1561 } 1562 } 1563 if (optind < argc) 1564 open_filesystem(argv[optind], open_flags, 1565 superblock, blocksize, catastrophic); 1566 1567 sci_idx = ss_create_invocation("debugfs", "0.0", (char *) NULL, 1568 &debug_cmds, &retval); 1569 if (retval) { 1570 ss_perror(sci_idx, retval, "creating invocation"); 1571 exit(1); 1572 } 1573 1574 (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval); 1575 if (retval) { 1576 ss_perror(sci_idx, retval, "adding standard requests"); 1577 exit (1); 1578 } 1579 if (request) { 1580 retval = 0; 1581 retval = ss_execute_line(sci_idx, request); 1582 if (retval) { 1583 ss_perror(sci_idx, retval, request); 1584 exit_status++; 1585 } 1586 } else if (cmd_file) { 1587 exit_status = source_file(cmd_file, sci_idx); 1588 } else { 1589 ss_listen(sci_idx); 1590 } 1591 1592 if (current_fs) 1593 close_filesystem(); 1594 1595 return exit_status; 1596} 1597