test_rel.c revision 521e36857227b21e7ab47b0a97f788d2af9f9717
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 <linux/ext2_fs.h> 22 23#include <et/com_err.h> 24#include <ss/ss.h> 25#include <ext2fs/ext2fs.h> 26#include <ext2fs/irel.h> 27#include <ext2fs/brel.h> 28 29#include "test_rel.h" 30 31extern ss_request_table test_cmds; 32 33ext2_irel irel = NULL; 34ext2_brel brel = NULL; 35 36/* 37 * Helper function which parses an inode number. 38 */ 39static int parse_inode(const char *request, const char *desc, 40 const char *str, 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 */ 55static 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 */ 71static 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 */ 82static 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 */ 93static 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 */ 103static void display_irel_entry(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 */ 144void 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 164void 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 173void 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 214void 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 238void 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 253void 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 275void 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 304void 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 329void 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 351void do_irel_ma_create(int argc, char **argv) 352{ 353 const char *usage = "Usage: %s name max_inode\n"; 354 errcode_t retval; 355 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 371void 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 381void do_irel_put(int argc, char **argv) 382{ 383 const char *usage = "%s old new max_refs"; 384 struct ext2_inode_relocate_entry ent; 385 errcode_t retval; 386 ino_t old, new, max_refs; 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 417void do_irel_get(int argc, char **argv) 418{ 419 const char *usage = "%s inode"; 420 struct ext2_inode_relocate_entry ent; 421 errcode_t retval; 422 ino_t old; 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 443void do_irel_get_by_orig(int argc, char **argv) 444{ 445 const char *usage = "%s orig_inode"; 446 errcode_t retval; 447 struct ext2_inode_relocate_entry ent; 448 ino_t orig, old; 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 469void 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 484void do_irel_next(int argc, char **argv) 485{ 486 errcode_t retval; 487 struct ext2_inode_relocate_entry ent; 488 ino_t old; 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 506void do_irel_dump(int argc, char **argv) 507{ 508 errcode_t retval; 509 struct ext2_inode_relocate_entry ent; 510 ino_t ino; 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 535void do_irel_add_ref(int argc, char **argv) 536{ 537 const char *usage = "%s inode block offset"; 538 errcode_t retval; 539 struct ext2_inode_reference ref; 540 blk_t block, offset; 541 ino_t ino; 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 572void do_irel_start_iter_ref(int argc, char **argv) 573{ 574 const char *usage = "%s inode"; 575 errcode_t retval; 576 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 596void 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 613void do_irel_move(int argc, char **argv) 614{ 615 const char *usage = "%s old new"; 616 errcode_t retval; 617 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 639void do_irel_delete(int argc, char **argv) 640{ 641 const char *usage = "%s inode"; 642 errcode_t retval; 643 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 663static 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 setbuf(stdout, NULL); 682 setbuf(stderr, NULL); 683 while (!feof(f)) { 684 if (fgets(buf, sizeof(buf), f) == NULL) 685 break; 686 if (buf[0] == '#') 687 continue; 688 noecho = 0; 689 if (buf[0] == '-') { 690 noecho = 1; 691 buf[0] = ' '; 692 } 693 cp = strchr(buf, '\n'); 694 if (cp) 695 *cp = 0; 696 cp = strchr(buf, '\r'); 697 if (cp) 698 *cp = 0; 699 if (!noecho) 700 printf("test_rel: %s\n", buf); 701 retval = ss_execute_line(sci_idx, buf); 702 if (retval) { 703 ss_perror(sci_idx, retval, buf); 704 exit_status++; 705 } 706 } 707 return exit_status; 708} 709 710void main(int argc, char **argv) 711{ 712 int retval; 713 int sci_idx; 714 const char *usage = "Usage: test_rel [-R request] [-f cmd_file]"; 715 char c; 716 char *request = 0; 717 int exit_status = 0; 718 char *cmd_file = 0; 719 720 initialize_ext2_error_table(); 721 722 while ((c = getopt (argc, argv, "wR:f:")) != EOF) { 723 switch (c) { 724 case 'R': 725 request = optarg; 726 break; 727 case 'f': 728 cmd_file = optarg; 729 break; 730 default: 731 com_err(argv[0], 0, usage); 732 return; 733 } 734 } 735 sci_idx = ss_create_invocation("test_rel", "0.0", (char *) NULL, 736 &test_cmds, &retval); 737 if (retval) { 738 ss_perror(sci_idx, retval, "creating invocation"); 739 exit(1); 740 } 741 742 (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval); 743 if (retval) { 744 ss_perror(sci_idx, retval, "adding standard requests"); 745 exit (1); 746 } 747 if (request) { 748 retval = 0; 749 retval = ss_execute_line(sci_idx, request); 750 if (retval) { 751 ss_perror(sci_idx, retval, request); 752 exit_status++; 753 } 754 } else if (cmd_file) { 755 exit_status = source_file(cmd_file, sci_idx); 756 } else { 757 ss_listen(sci_idx); 758 } 759 760 exit(exit_status); 761} 762 763