1 /* 2 * test_rel.c 3 * 4 * Copyright (C) 1997 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Public 8 * License. 9 * %End-Header% 10 */ 11 12 #include "config.h" 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <unistd.h> 17 #ifdef HAVE_GETOPT_H 18 #include <getopt.h> 19 #endif 20 #include <fcntl.h> 21 22 #include <et/com_err.h> 23 #include <ss/ss.h> 24 #include <ext2fs/ext2_fs.h> 25 #include <ext2fs/ext2fs.h> 26 #include <ext2fs/irel.h> 27 #include <ext2fs/brel.h> 28 29 #include "test_rel.h" 30 31 extern ss_request_table test_cmds; 32 33 ext2_irel irel = NULL; 34 ext2_brel brel = NULL; 35 36 /* 37 * Helper function which parses an inode number. 38 */ parse_inode(const char * request,const char * desc,const char * str,ext2_ino_t * ino)39 static int parse_inode(const char *request, const char *desc, 40 const char *str, ext2_ino_t *ino) 41 { 42 char *tmp; 43 44 *ino = strtoul(str, &tmp, 0); 45 if (*tmp) { 46 com_err(request, 0, "Bad %s - %s", desc, str); 47 return 1; 48 } 49 return 0; 50 } 51 52 /* 53 * Helper function which parses a block number. 54 */ parse_block(const char * request,const char * desc,const char * str,blk_t * blk)55 static int parse_block(const char *request, const char *desc, 56 const char *str, blk_t *blk) 57 { 58 char *tmp; 59 60 *blk = strtoul(str, &tmp, 0); 61 if (*tmp) { 62 com_err(request, 0, "Bad %s - %s", desc, str); 63 return 1; 64 } 65 return 0; 66 } 67 68 /* 69 * Helper function which assures that a brel table is open 70 */ check_brel(char * request)71 static int check_brel(char *request) 72 { 73 if (brel) 74 return 0; 75 com_err(request, 0, "A block relocation table must be open."); 76 return 1; 77 } 78 79 /* 80 * Helper function which assures that an irel table is open 81 */ check_irel(char * request)82 static int check_irel(char *request) 83 { 84 if (irel) 85 return 0; 86 com_err(request, 0, "An inode relocation table must be open."); 87 return 1; 88 } 89 90 /* 91 * Helper function which displays a brel entry 92 */ display_brel_entry(blk_t old,struct ext2_block_relocate_entry * ent)93 static void display_brel_entry(blk_t old, 94 struct ext2_block_relocate_entry *ent) 95 { 96 printf("Old= %u, New= %u, Owner= %u:%u\n", old, ent->new, 97 ent->owner.block_ref, ent->offset); 98 } 99 100 /* 101 * Helper function which displays an irel entry 102 */ display_irel_entry(ext2_ino_t old,struct ext2_inode_relocate_entry * ent,int do_refs)103 static void display_irel_entry(ext2_ino_t old, 104 struct ext2_inode_relocate_entry *ent, 105 int do_refs) 106 { 107 struct ext2_inode_reference ref; 108 errcode_t retval; 109 int first = 1; 110 111 printf("Old= %lu, New= %lu, Original=%lu, Max_refs=%u\n", old, 112 ent->new, ent->orig, ent->max_refs); 113 if (!do_refs) 114 return; 115 116 retval = ext2fs_irel_start_iter_ref(irel, old); 117 if (retval) { 118 printf("\tCouldn't get references: %s\n", 119 error_message(retval)); 120 return; 121 } 122 while (1) { 123 retval = ext2fs_irel_next_ref(irel, &ref); 124 if (retval) { 125 printf("(%s) ", error_message(retval)); 126 break; 127 } 128 if (ref.block == 0) 129 break; 130 if (first) { 131 fputc('\t', stdout); 132 first = 0; 133 } else 134 printf(", "); 135 printf("%u:%u", ref.block, ref.offset); 136 } 137 if (!first) 138 fputc('\n', stdout); 139 } 140 141 /* 142 * These are the actual command table procedures 143 */ do_brel_ma_create(int argc,char ** argv)144 void do_brel_ma_create(int argc, char **argv) 145 { 146 const char *usage = "Usage: %s name max_blocks\n"; 147 errcode_t retval; 148 blk_t max_blk; 149 150 if (argc < 3) { 151 printf(usage, argv[0]); 152 return; 153 } 154 if (parse_block(argv[0], "max_blocks", argv[2], &max_blk)) 155 return; 156 retval = ext2fs_brel_memarray_create(argv[1], max_blk, &brel); 157 if (retval) { 158 com_err(argv[0], retval, "while opening memarray brel"); 159 return; 160 } 161 return; 162 } 163 do_brel_free(int argc,char ** argv)164 void do_brel_free(int argc, char **argv) 165 { 166 if (check_brel(argv[0])) 167 return; 168 ext2fs_brel_free(brel); 169 brel = NULL; 170 return; 171 } 172 do_brel_put(int argc,char ** argv)173 void do_brel_put(int argc, char **argv) 174 { 175 const char *usage = "usage: %s old_block new_block [owner] [offset]"; 176 errcode_t retval; 177 struct ext2_block_relocate_entry ent; 178 blk_t old, new, offset=0, owner=0; 179 180 if (check_brel(argv[0])) 181 return; 182 183 if (argc < 3) { 184 printf(usage, argv[0]); 185 return; 186 } 187 if (parse_block(argv[0], "old block", argv[1], &old)) 188 return; 189 if (parse_block(argv[0], "new block", argv[2], &new)) 190 return; 191 if (argc > 3 && 192 parse_block(argv[0], "owner block", argv[3], &owner)) 193 return; 194 if (argc > 4 && 195 parse_block(argv[0], "offset", argv[4], &offset)) 196 return; 197 if (offset > 65535) { 198 printf("Offset too large.\n"); 199 return; 200 } 201 ent.new = new; 202 ent.offset = (__u16) offset; 203 ent.flags = 0; 204 ent.owner.block_ref = owner; 205 206 retval = ext2fs_brel_put(brel, old, &ent); 207 if (retval) { 208 com_err(argv[0], retval, "while calling ext2fs_brel_put"); 209 return; 210 } 211 return; 212 } 213 do_brel_get(int argc,char ** argv)214 void do_brel_get(int argc, char **argv) 215 { 216 const char *usage = "%s block"; 217 errcode_t retval; 218 struct ext2_block_relocate_entry ent; 219 blk_t blk; 220 221 if (check_brel(argv[0])) 222 return; 223 if (argc < 2) { 224 printf(usage, argv[0]); 225 return; 226 } 227 if (parse_block(argv[0], "block", argv[1], &blk)) 228 return; 229 retval = ext2fs_brel_get(brel, blk, &ent); 230 if (retval) { 231 com_err(argv[0], retval, "while calling ext2fs_brel_get"); 232 return; 233 } 234 display_brel_entry(blk, &ent); 235 return; 236 } 237 do_brel_start_iter(int argc,char ** argv)238 void do_brel_start_iter(int argc, char **argv) 239 { 240 errcode_t retval; 241 242 if (check_brel(argv[0])) 243 return; 244 245 retval = ext2fs_brel_start_iter(brel); 246 if (retval) { 247 com_err(argv[0], retval, "while calling ext2fs_brel_start_iter"); 248 return; 249 } 250 return; 251 } 252 do_brel_next(int argc,char ** argv)253 void do_brel_next(int argc, char **argv) 254 { 255 errcode_t retval; 256 struct ext2_block_relocate_entry ent; 257 blk_t blk; 258 259 if (check_brel(argv[0])) 260 return; 261 262 retval = ext2fs_brel_next(brel, &blk, &ent); 263 if (retval) { 264 com_err(argv[0], retval, "while calling ext2fs_brel_next"); 265 return; 266 } 267 if (blk == 0) { 268 printf("No more entries!\n"); 269 return; 270 } 271 display_brel_entry(blk, &ent); 272 return; 273 } 274 do_brel_dump(int argc,char ** argv)275 void do_brel_dump(int argc, char **argv) 276 { 277 errcode_t retval; 278 struct ext2_block_relocate_entry ent; 279 blk_t blk; 280 281 if (check_brel(argv[0])) 282 return; 283 284 retval = ext2fs_brel_start_iter(brel); 285 if (retval) { 286 com_err(argv[0], retval, "while calling ext2fs_brel_start_iter"); 287 return; 288 } 289 290 while (1) { 291 retval = ext2fs_brel_next(brel, &blk, &ent); 292 if (retval) { 293 com_err(argv[0], retval, "while calling ext2fs_brel_next"); 294 return; 295 } 296 if (blk == 0) 297 break; 298 299 display_brel_entry(blk, &ent); 300 } 301 return; 302 } 303 do_brel_move(int argc,char ** argv)304 void do_brel_move(int argc, char **argv) 305 { 306 const char *usage = "%s old_block new_block"; 307 errcode_t retval; 308 blk_t old, new; 309 310 if (check_brel(argv[0])) 311 return; 312 if (argc < 2) { 313 printf(usage, argv[0]); 314 return; 315 } 316 if (parse_block(argv[0], "old block", argv[1], &old)) 317 return; 318 if (parse_block(argv[0], "new block", argv[2], &new)) 319 return; 320 321 retval = ext2fs_brel_move(brel, old, new); 322 if (retval) { 323 com_err(argv[0], retval, "while calling ext2fs_brel_move"); 324 return; 325 } 326 return; 327 } 328 do_brel_delete(int argc,char ** argv)329 void do_brel_delete(int argc, char **argv) 330 { 331 const char *usage = "%s block"; 332 errcode_t retval; 333 blk_t blk; 334 335 if (check_brel(argv[0])) 336 return; 337 if (argc < 2) { 338 printf(usage, argv[0]); 339 return; 340 } 341 if (parse_block(argv[0], "block", argv[1], &blk)) 342 return; 343 344 retval = ext2fs_brel_delete(brel, blk); 345 if (retval) { 346 com_err(argv[0], retval, "while calling ext2fs_brel_delete"); 347 return; 348 } 349 } 350 do_irel_ma_create(int argc,char ** argv)351 void do_irel_ma_create(int argc, char **argv) 352 { 353 const char *usage = "Usage: %s name max_inode\n"; 354 errcode_t retval; 355 ext2_ino_t max_ino; 356 357 if (argc < 3) { 358 printf(usage, argv[0]); 359 return; 360 } 361 if (parse_inode(argv[0], "max_inodes", argv[2], &max_ino)) 362 return; 363 retval = ext2fs_irel_memarray_create(argv[1], max_ino, &irel); 364 if (retval) { 365 com_err(argv[0], retval, "while opening memarray irel"); 366 return; 367 } 368 return; 369 } 370 do_irel_free(int argc,char ** argv)371 void do_irel_free(int argc, char **argv) 372 { 373 if (check_irel(argv[0])) 374 return; 375 376 ext2fs_irel_free(irel); 377 irel = NULL; 378 return; 379 } 380 do_irel_put(int argc,char ** argv)381 void do_irel_put(int argc, char **argv) 382 { 383 const char *usage = "%s old new max_refs"; 384 errcode_t retval; 385 ext2_ino_t old, new, max_refs; 386 struct ext2_inode_relocate_entry ent; 387 388 if (check_irel(argv[0])) 389 return; 390 391 if (argc < 4) { 392 printf(usage, argv[0]); 393 return; 394 } 395 if (parse_inode(argv[0], "old inode", argv[1], &old)) 396 return; 397 if (parse_inode(argv[0], "new inode", argv[2], &new)) 398 return; 399 if (parse_inode(argv[0], "max_refs", argv[3], &max_refs)) 400 return; 401 if (max_refs > 65535) { 402 printf("max_refs too big\n"); 403 return; 404 } 405 ent.new = new; 406 ent.max_refs = (__u16) max_refs; 407 ent.flags = 0; 408 409 retval = ext2fs_irel_put(irel, old, &ent); 410 if (retval) { 411 com_err(argv[0], retval, "while calling ext2fs_irel_put"); 412 return; 413 } 414 return; 415 } 416 do_irel_get(int argc,char ** argv)417 void do_irel_get(int argc, char **argv) 418 { 419 const char *usage = "%s inode"; 420 errcode_t retval; 421 ext2_ino_t old; 422 struct ext2_inode_relocate_entry ent; 423 424 if (check_irel(argv[0])) 425 return; 426 427 if (argc < 2) { 428 printf(usage, argv[0]); 429 return; 430 } 431 if (parse_inode(argv[0], "inode", argv[1], &old)) 432 return; 433 434 retval = ext2fs_irel_get(irel, old, &ent); 435 if (retval) { 436 com_err(argv[0], retval, "while calling ext2fs_irel_get"); 437 return; 438 } 439 display_irel_entry(old, &ent, 1); 440 return; 441 } 442 do_irel_get_by_orig(int argc,char ** argv)443 void do_irel_get_by_orig(int argc, char **argv) 444 { 445 const char *usage = "%s orig_inode"; 446 errcode_t retval; 447 ext2_ino_t orig, old; 448 struct ext2_inode_relocate_entry ent; 449 450 if (check_irel(argv[0])) 451 return; 452 453 if (argc < 2) { 454 printf(usage, argv[0]); 455 return; 456 } 457 if (parse_inode(argv[0], "original inode", argv[1], &orig)) 458 return; 459 460 retval = ext2fs_irel_get_by_orig(irel, orig, &old, &ent); 461 if (retval) { 462 com_err(argv[0], retval, "while calling ext2fs_irel_get_by_orig"); 463 return; 464 } 465 display_irel_entry(old, &ent, 1); 466 return; 467 } 468 do_irel_start_iter(int argc,char ** argv)469 void do_irel_start_iter(int argc, char **argv) 470 { 471 errcode_t retval; 472 473 if (check_irel(argv[0])) 474 return; 475 476 retval = ext2fs_irel_start_iter(irel); 477 if (retval) { 478 com_err(argv[0], retval, "while calling ext2fs_irel_start_iter"); 479 return; 480 } 481 return; 482 } 483 do_irel_next(int argc,char ** argv)484 void do_irel_next(int argc, char **argv) 485 { 486 errcode_t retval; 487 ext2_ino_t old; 488 struct ext2_inode_relocate_entry ent; 489 490 if (check_irel(argv[0])) 491 return; 492 493 retval = ext2fs_irel_next(irel, &old, &ent); 494 if (retval) { 495 com_err(argv[0], retval, "while calling ext2fs_irel_next"); 496 return; 497 } 498 if (old == 0) { 499 printf("No more entries!\n"); 500 return; 501 } 502 display_irel_entry(old, &ent, 1); 503 return; 504 } 505 do_irel_dump(int argc,char ** argv)506 void do_irel_dump(int argc, char **argv) 507 { 508 errcode_t retval; 509 ext2_ino_t ino; 510 struct ext2_inode_relocate_entry ent; 511 512 if (check_irel(argv[0])) 513 return; 514 515 retval = ext2fs_irel_start_iter(irel); 516 if (retval) { 517 com_err(argv[0], retval, "while calling ext2fs_irel_start_iter"); 518 return; 519 } 520 521 while (1) { 522 retval = ext2fs_irel_next(irel, &ino, &ent); 523 if (retval) { 524 com_err(argv[0], retval, "while calling ext2fs_irel_next"); 525 return; 526 } 527 if (ino == 0) 528 break; 529 530 display_irel_entry(ino, &ent, 1); 531 } 532 return; 533 } 534 do_irel_add_ref(int argc,char ** argv)535 void do_irel_add_ref(int argc, char **argv) 536 { 537 const char *usage = "%s inode block offset"; 538 errcode_t retval; 539 blk_t block, offset; 540 ext2_ino_t ino; 541 struct ext2_inode_reference ref; 542 543 544 if (check_irel(argv[0])) 545 return; 546 547 if (argc < 4) { 548 printf(usage, argv[0]); 549 return; 550 } 551 if (parse_inode(argv[0], "inode", argv[1], &ino)) 552 return; 553 if (parse_block(argv[0], "block", argv[2], &block)) 554 return; 555 if (parse_block(argv[0], "offset", argv[3], &offset)) 556 return; 557 if (offset > 65535) { 558 printf("Offset too big.\n"); 559 return; 560 } 561 ref.block = block; 562 ref.offset = offset; 563 564 retval = ext2fs_irel_add_ref(irel, ino, &ref); 565 if (retval) { 566 com_err(argv[0], retval, "while calling ext2fs_irel_add_ref"); 567 return; 568 } 569 return; 570 } 571 do_irel_start_iter_ref(int argc,char ** argv)572 void do_irel_start_iter_ref(int argc, char **argv) 573 { 574 const char *usage = "%s inode"; 575 errcode_t retval; 576 ext2_ino_t ino; 577 578 if (check_irel(argv[0])) 579 return; 580 581 if (argc < 2) { 582 printf(usage, argv[0]); 583 return; 584 } 585 586 if (parse_inode(argv[0], "inode", argv[1], &ino)) 587 return; 588 retval = ext2fs_irel_start_iter_ref(irel, ino); 589 if (retval) { 590 com_err(argv[0], retval, "while calling ext2fs_irel_start_iter_ref"); 591 return; 592 } 593 return; 594 } 595 do_irel_next_ref(int argc,char ** argv)596 void do_irel_next_ref(int argc, char **argv) 597 { 598 struct ext2_inode_reference ref; 599 errcode_t retval; 600 601 if (check_irel(argv[0])) 602 return; 603 604 retval = ext2fs_irel_next_ref(irel, &ref); 605 if (retval) { 606 com_err(argv[0], retval, "while calling ext2fs_irel_next_ref"); 607 return; 608 } 609 printf("Inode reference: %u:%u\n", ref.block, ref.offset); 610 return; 611 } 612 do_irel_move(int argc,char ** argv)613 void do_irel_move(int argc, char **argv) 614 { 615 const char *usage = "%s old new"; 616 errcode_t retval; 617 ext2_ino_t old, new; 618 619 if (check_irel(argv[0])) 620 return; 621 622 if (argc < 3) { 623 printf(usage, argv[0]); 624 return; 625 } 626 if (parse_inode(argv[0], "old inode", argv[1], &old)) 627 return; 628 if (parse_inode(argv[0], "new inode", argv[2], &new)) 629 return; 630 631 retval = ext2fs_irel_move(irel, old, new); 632 if (retval) { 633 com_err(argv[0], retval, "while calling ext2fs_irel_move"); 634 return; 635 } 636 return; 637 } 638 do_irel_delete(int argc,char ** argv)639 void do_irel_delete(int argc, char **argv) 640 { 641 const char *usage = "%s inode"; 642 errcode_t retval; 643 ext2_ino_t ino; 644 645 if (check_irel(argv[0])) 646 return; 647 648 if (argc < 2) { 649 printf(usage, argv[0]); 650 return; 651 } 652 if (parse_inode(argv[0], "inode", argv[1], &ino)) 653 return; 654 655 retval = ext2fs_irel_delete(irel, ino); 656 if (retval) { 657 com_err(argv[0], retval, "while calling ext2fs_irel_delete"); 658 return; 659 } 660 return; 661 } 662 source_file(const char * cmd_file,int sci_idx)663 static int source_file(const char *cmd_file, int sci_idx) 664 { 665 FILE *f; 666 char buf[256]; 667 char *cp; 668 int exit_status = 0; 669 int retval; 670 int noecho; 671 672 if (strcmp(cmd_file, "-") == 0) 673 f = stdin; 674 else { 675 f = fopen(cmd_file, "r"); 676 if (!f) { 677 perror(cmd_file); 678 exit(1); 679 } 680 } 681 fflush(stdout); 682 fflush(stderr); 683 setbuf(stdout, NULL); 684 setbuf(stderr, NULL); 685 while (!feof(f)) { 686 if (fgets(buf, sizeof(buf), f) == NULL) 687 break; 688 if (buf[0] == '#') 689 continue; 690 noecho = 0; 691 if (buf[0] == '-') { 692 noecho = 1; 693 buf[0] = ' '; 694 } 695 cp = strchr(buf, '\n'); 696 if (cp) 697 *cp = 0; 698 cp = strchr(buf, '\r'); 699 if (cp) 700 *cp = 0; 701 if (!noecho) 702 printf("test_rel: %s\n", buf); 703 retval = ss_execute_line(sci_idx, buf); 704 if (retval) { 705 ss_perror(sci_idx, retval, buf); 706 exit_status++; 707 } 708 } 709 return exit_status; 710 } 711 main(int argc,char ** argv)712 void main(int argc, char **argv) 713 { 714 int retval; 715 int sci_idx; 716 const char *usage = "Usage: test_rel [-R request] [-f cmd_file]"; 717 int c; 718 char *request = 0; 719 int exit_status = 0; 720 char *cmd_file = 0; 721 722 initialize_ext2_error_table(); 723 724 while ((c = getopt (argc, argv, "wR:f:")) != EOF) { 725 switch (c) { 726 case 'R': 727 request = optarg; 728 break; 729 case 'f': 730 cmd_file = optarg; 731 break; 732 default: 733 com_err(argv[0], 0, usage); 734 return; 735 } 736 } 737 sci_idx = ss_create_invocation("test_rel", "0.0", (char *) NULL, 738 &test_cmds, &retval); 739 if (retval) { 740 ss_perror(sci_idx, retval, "creating invocation"); 741 exit(1); 742 } 743 744 (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval); 745 if (retval) { 746 ss_perror(sci_idx, retval, "adding standard requests"); 747 exit (1); 748 } 749 if (request) { 750 retval = 0; 751 retval = ss_execute_line(sci_idx, request); 752 if (retval) { 753 ss_perror(sci_idx, retval, request); 754 exit_status++; 755 } 756 } else if (cmd_file) { 757 exit_status = source_file(cmd_file, sci_idx); 758 } else { 759 ss_listen(sci_idx); 760 } 761 762 exit(exit_status); 763 } 764 765