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