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