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