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