1 %{ 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License, Version 1.0 only 7 * (the "License"). You may not use this file except in compliance 8 * with the License. 9 * 10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 * or http://www.opensolaris.org/os/licensing. 12 * See the License for the specific language governing permissions 13 * and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 * 23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #include <stdio.h> 28 #include <locale.h> 29 #include <sys/param.h> 30 #include <sys/fs/udf_volume.h> 31 32 char shell_name[128] = "/bin/sh"; 33 extern char prompt[]; 34 extern uint16_t ricb_prn; 35 extern uint32_t ricb_loc; 36 extern int32_t bsize, bmask, l2d, l2b; 37 38 int base = 16; 39 int old_value = 0; 40 int value = 0; 41 int count = 0; 42 43 44 int last_op_type = 0; 45 #define TYPE_NONE 0 46 #define TYPE_INODE 1 47 #define TYPE_DIRENT 2 48 #define TYPE_BLOCK 3 49 #define TYPE_CD 4 50 51 uint32_t i_number = 0; 52 uint32_t d_entry = 0; 53 int error_override = 0; 54 55 int register_array[256]; 56 char cwd[MAXPATHLEN] = "/"; 57 58 int32_t ls_flags; 59 #define LONG_LIST 0x1 60 #define RECU_LIST 0x2 61 #define LIST_LS 0x4 62 63 int32_t find_flags; 64 #define FIND_DIR 0x1 65 #define FIND_NAME 0x2 66 #define FIND_INODE 0x4 67 #define FIND_DONE 0x8 68 char find_dir[1024]; 69 char find_name[1024]; 70 uint32_t find_in; 71 72 %} 73 74 %union 75 { 76 uint8_t *strval; 77 uint64_t intval; 78 }; 79 80 %token BASE BLOCK CD DIRECTORY TFILE FIND FILL 81 %token INODE LS OVERRIDE PROMPT PWD QUIT TAG BANG 82 83 %token AVD MVDS RVDS INTS FSDS ROOT 84 %token ATTZ ATYE ATMO ATDA ATHO ATMI ATSE ATCE ATHU ATMIC 85 %token CTTZ CTYE CTMO CTDA CTHO CTMI CTSE CTCE CTHU CTMIC 86 %token MTTZ MTYE MTMO MTDA MTHO MTMI MTSE MTCE MTHU MTMIC 87 %token GID LN MD MAJ MIO NM SZ UID UNIQ 88 %token DOT 89 %token NL 90 91 %token WORD 92 93 %left '-' '+' 94 %left '*' '%' 95 96 %type <strval> WORD 97 %type <intval> expr 98 99 %% 100 101 session : statement_list 102 103 statement_list : /* empty */ { print_prompt(); } 104 | statement_list statement 105 { 106 ls_flags = 0; 107 } 108 ; 109 110 statement : empty_statement 111 | current_value 112 | register 113 | base | block | cd | directory | file | find | fill 114 | inode | ls | override | nprompt | pwd | quit | tag | shell 115 | avd | mvds | rvds | ints | fsds | root 116 | at | ct | gid | ln | mt | md 117 | maj | min | nm | sz | uid | uniq 118 | dump | texpr 119 | error { yyclearin; yyerrok; } 120 ; 121 122 empty_statement : NL 123 { 124 print_prompt(); 125 } 126 ; 127 128 129 current_value : DOT 130 { 131 if (last_op_type == TYPE_INODE) { 132 print_inode(i_number << l2b); 133 } else if (last_op_type == TYPE_DIRENT) { 134 print_dent(i_number << l2b, d_entry); 135 } else { 136 fprintf(stdout, 137 gettext("%x\n"), value); 138 } 139 } 140 ; 141 142 register : '<' WORD 143 { 144 if ((strlen((caddr_t)$2) == 1) && 145 ((($2[0] >= 'a') && 146 ($2[0] <= 'z')) || 147 (($2[0] >= 'A') && 148 ($2[0] <= 'Z')))) { 149 value = register_array[$2[0]]; 150 } else { 151 fprintf(stdout, 152 gettext("Registers can" 153 " be only a-z or A-Z\n")); 154 } 155 } 156 | '>' WORD 157 { 158 if ((strlen((caddr_t)$2) == 1) && 159 ((($2[0] >= 'a') && 160 ($2[0] <= 'z')) || 161 (($2[0] >= 'A') && 162 ($2[0] <= 'Z')))) { 163 register_array[$2[0]] = value; 164 } else { 165 fprintf(stdout, 166 gettext("Registers can" 167 " be only a-z or A-Z\n")); 168 } 169 } 170 ; 171 172 base : BASE '=' expr 173 { 174 if (($3 == 8) || ($3 == 10) || ($3 == 16)) { 175 base = $3; 176 } else { 177 fprintf(stdout, 178 gettext("Requested %x Only" 179 " Oct, Dec and" 180 " Hex are Supported\n"), $3); 181 } 182 } 183 | BASE 184 { 185 fprintf(stdout, 186 gettext("Current Base in Decimal" 187 " : %d\n"), base); 188 } 189 ; 190 191 block : BLOCK 192 { 193 last_op_type = TYPE_NONE; 194 value = value * DEV_BSIZE; 195 } 196 ; 197 198 cd : CD ' ' WORD 199 { 200 uint8_t fl; 201 uint32_t temp; 202 char temp_cwd[MAXPATHLEN]; 203 204 strcpy(temp_cwd, cwd); 205 if (strcmp((caddr_t)$3, "..") == 0) { 206 if (strlen(temp_cwd) == 1) { 207 if (temp_cwd[0] != '/') { 208 fprintf(stdout, 209 gettext("cwd is invalid" 210 "setting to /\n")); 211 strcpy(temp_cwd, "/"); 212 } 213 } else { 214 dirname(temp_cwd); 215 } 216 } else { 217 int32_t len; 218 219 len = strlen(temp_cwd); 220 if (temp_cwd[len - 1] != '/') { 221 temp_cwd[len] = '/'; 222 temp_cwd[len + 1] = '\0'; 223 } 224 strcat(temp_cwd, (caddr_t)$3); 225 } 226 if (inode_from_path(temp_cwd, &temp, 227 &fl) != 0) { 228 fprintf(stdout, 229 gettext("Could not locate inode" 230 " for path %s\n"), temp_cwd); 231 strcpy(temp_cwd, "/"); 232 if ((temp = ud_xlate_to_daddr(ricb_prn, 233 ricb_loc)) == 0) { 234 fprintf(stdout, 235 gettext("Failed to translate" 236 " prn %x loc %x\n"), 237 ricb_prn, ricb_loc); 238 } 239 } else { 240 if ((fl & FID_DIR) == 0) { 241 fprintf(stdout, 242 gettext("%s is not a" 243 " directory\n"), temp_cwd); 244 } else { 245 strcpy(cwd, temp_cwd); 246 value = temp << l2b; 247 last_op_type = TYPE_CD; 248 i_number = temp; 249 } 250 } 251 } 252 | CD 253 { 254 uint32_t block; 255 256 (void) strcpy(cwd, "/"); 257 /* 258 * set current value to root icb 259 */ 260 if ((block = ud_xlate_to_daddr(ricb_prn, 261 ricb_loc)) == 0) { 262 fprintf(stdout, 263 gettext("Failed to translate " 264 "prn %x loc %x\n"), 265 ricb_prn, ricb_loc); 266 } else { 267 value = block << l2b; 268 last_op_type = TYPE_CD; 269 i_number = block; 270 } 271 } 272 ; 273 274 directory : DIRECTORY 275 { 276 if (verify_dent(i_number << l2b, value) == 0) { 277 last_op_type = TYPE_DIRENT; 278 d_entry = value; 279 } 280 } 281 ; 282 283 file : TFILE 284 { 285 } 286 ; 287 288 find : xfind 289 { 290 if ((find_flags & (FIND_NAME | FIND_INODE)) && 291 (find_flags & FIND_DONE)) { 292 if (find_dir[0] != '/') { 293 char buf[1024]; 294 295 strcpy(buf, find_dir); 296 if ((strlen(cwd) == 1) && 297 (cwd[0] == '/')) { 298 strcpy(find_dir, "/"); 299 } else { 300 strcpy(find_dir, cwd); 301 strcat(find_dir, "/"); 302 } 303 strcat(find_dir, buf); 304 } 305 find_it(find_dir, find_name, find_in, 306 (find_flags & (FIND_NAME | FIND_INODE))); 307 } 308 find_flags = 0; 309 find_dir[0] = '\0'; 310 find_name[0] = '\0'; 311 find_in = 0; 312 } 313 ; 314 315 xfind : FIND WORD 316 { 317 strcpy(find_dir, (char *)$2); 318 find_flags = FIND_DIR; 319 } 320 | xfind ' ' WORD 321 { 322 if (find_flags == FIND_DIR) { 323 if (strcmp((char *)$3, "-name") == 0) { 324 find_flags = FIND_NAME; 325 } else if (strcmp((char *)$3, "-inum") 326 == 0) { 327 find_flags = FIND_INODE; 328 } else { 329 fprintf(stdout, 330 gettext("find dir-name {-name n | -inum n}\n")); 331 } 332 } else if (find_flags == FIND_NAME) { 333 strcpy(find_name, (char *)$3); 334 find_flags |= FIND_DONE; 335 } else if (find_flags == FIND_INODE) { 336 uint64_t temp; 337 338 if (check_and_get_int($3, &temp) == 339 0) { 340 find_in = temp; 341 find_flags |= FIND_DONE; 342 } else { 343 fprintf(stdout, 344 gettext("find dir-name {-name n | -inum n}\n")); 345 } 346 } else { 347 fprintf(stdout, 348 gettext("find dir-name {-name n | -inum n}\n")); 349 } 350 } 351 | xfind ' ' expr 352 { 353 if (find_flags == FIND_INODE) { 354 find_in = $3; 355 find_flags |= FIND_DONE; 356 } else { 357 fprintf(stdout, 358 gettext("find dir-name {-name n | -inum n}\n")); 359 } 360 } 361 ; 362 363 364 fill : FILL '=' WORD 365 { 366 fill_pattern(value, count, $3); 367 } 368 ; 369 370 inode : INODE 371 { 372 uint32_t temp; 373 374 if (last_op_type == TYPE_CD) { 375 temp = value; 376 } else { 377 temp = value << l2b; 378 } 379 last_op_type = TYPE_INODE; 380 if (verify_inode(temp, 0) != 0) { 381 i_number = temp >> l2b; 382 d_entry = 0; 383 } 384 } 385 ; 386 387 ls : xls 388 { 389 if (ls_flags & LIST_LS) { 390 list(".", i_number, ls_flags); 391 } 392 } 393 ; 394 395 xls : LS 396 { 397 /* Do nothing */ 398 ls_flags = LIST_LS; 399 } 400 | xls ' ' WORD 401 { 402 if (strcmp((caddr_t)$3, "-l") == 0) { 403 ls_flags |= LONG_LIST; 404 } else if (strcmp((caddr_t)$3, "-R") == 0) { 405 ls_flags |= RECU_LIST; 406 } else if ((strcmp((caddr_t)$3, "-lR") == 0) || 407 (strcmp((caddr_t)$3, "-Rl") == 0)) { 408 ls_flags |= LONG_LIST | RECU_LIST; 409 } else { 410 list(".", i_number, ls_flags); 411 ls_flags &= ~LIST_LS; 412 } 413 } 414 ; 415 416 override : OVERRIDE 417 { 418 if (error_override == 0) { 419 error_override = 1; 420 (void) fprintf(stdout, 421 gettext("error checking on\n")); 422 } else { 423 error_override = 0; 424 (void) fprintf(stdout, 425 gettext("error checking off\n")); 426 } 427 } 428 ; 429 430 nprompt : PROMPT '=' WORD 431 { 432 (void) strcpy(prompt, (caddr_t)$3); 433 } 434 ; 435 436 pwd : PWD 437 { 438 fprintf(stdout, gettext("%s\n"), cwd); 439 } 440 ; 441 442 quit : QUIT 443 { 444 exit (0); 445 } 446 ; 447 448 tag : TAG 449 { 450 print_desc(value, 0); 451 } 452 ; 453 454 shell : BANG 455 { 456 system(shell_name); 457 } 458 ; 459 460 avd : AVD { print_desc(NULL, AVD); } 461 ; 462 mvds : MVDS { print_desc(NULL, MVDS); } 463 ; 464 rvds : RVDS { print_desc(NULL, RVDS); } 465 ; 466 ints : INTS { print_desc(NULL, INTS); } 467 ; 468 fsds : FSDS { print_desc(NULL, FSDS); } 469 ; 470 root : ROOT { print_desc(NULL, ROOT); } 471 ; 472 473 at : ATTZ '=' expr { set_file(ATTZ, i_number << l2b, $3); } 474 | ATYE '=' expr { set_file(ATYE, i_number << l2b, $3); } 475 | ATMO '=' expr { set_file(ATMO, i_number << l2b, $3); } 476 | ATDA '=' expr { set_file(ATDA, i_number << l2b, $3); } 477 | ATHO '=' expr { set_file(ATHO, i_number << l2b, $3); } 478 | ATMI '=' expr { set_file(ATMI, i_number << l2b, $3); } 479 | ATSE '=' expr { set_file(ATSE, i_number << l2b, $3); } 480 | ATCE '=' expr { set_file(ATCE, i_number << l2b, $3); } 481 | ATHU '=' expr { set_file(ATHU, i_number << l2b, $3); } 482 | ATMIC '=' expr 483 { 484 set_file(ATMIC, i_number << l2b, $3); 485 } 486 ; 487 488 ct : CTTZ '=' expr { set_file(CTTZ, i_number << l2b, $3); } 489 | CTYE '=' expr { set_file(CTYE, i_number << l2b, $3); } 490 | CTMO '=' expr { set_file(CTMO, i_number << l2b, $3); } 491 | CTDA '=' expr { set_file(CTDA, i_number << l2b, $3); } 492 | CTHO '=' expr { set_file(CTHO, i_number << l2b, $3); } 493 | CTMI '=' expr { set_file(CTMI, i_number << l2b, $3); } 494 | CTSE '=' expr { set_file(CTSE, i_number << l2b, $3); } 495 | CTCE '=' expr { set_file(CTCE, i_number << l2b, $3); } 496 | CTHU '=' expr { set_file(CTHU, i_number << l2b, $3); } 497 | CTMIC '=' expr 498 { 499 set_file(CTMIC, i_number << l2b, $3); 500 } 501 ; 502 503 mt : MTTZ '=' expr { set_file(MTTZ, i_number << l2b, $3); } 504 | MTYE '=' expr { set_file(MTYE, i_number << l2b, $3); } 505 | MTMO '=' expr { set_file(MTMO, i_number << l2b, $3); } 506 | MTDA '=' expr { set_file(MTDA, i_number << l2b, $3); } 507 | MTHO '=' expr { set_file(MTHO, i_number << l2b, $3); } 508 | MTMI '=' expr { set_file(MTMI, i_number << l2b, $3); } 509 | MTSE '=' expr { set_file(MTSE, i_number << l2b, $3); } 510 | MTCE '=' expr { set_file(MTCE, i_number << l2b, $3); } 511 | MTHU '=' expr { set_file(MTHU, i_number << l2b, $3); } 512 | MTMIC '=' expr 513 { 514 set_file(MTMIC, i_number << l2b, $3); 515 } 516 ; 517 518 519 gid : GID '=' expr { set_file(GID, i_number << l2b, $3); } 520 ; 521 522 ln : LN '=' expr { set_file(LN, i_number << l2b, $3); } 523 ; 524 525 md : MD '=' expr { set_file(MD, i_number << l2b, $3); } 526 ; 527 528 maj : MAJ '=' expr { set_file(MAJ, i_number << l2b, $3); } 529 ; 530 531 min : MIO '=' expr { set_file(MIO, i_number << l2b, $3); } 532 ; 533 534 nm : NM '=' expr { set_file(NM, i_number << l2b, $3); } 535 ; 536 537 sz : SZ '=' expr { set_file(SZ, i_number << l2b, $3); } 538 ; 539 540 uid : UID '=' expr { set_file(UID, i_number << l2b, $3); } 541 ; 542 543 uniq : UNIQ '=' expr { set_file(UNIQ, i_number << l2b, $3); } 544 ; 545 546 dump : '/' WORD 547 { 548 if (strlen((char *)$2) != 1) { 549 fprintf(stdout, 550 gettext("Invalid command\n")); 551 } else { 552 dump_disk(value, count, $2); 553 } 554 } 555 | '?' WORD 556 { 557 if (strcmp((char *)$2, "i") == 0) { 558 if (verify_inode(value << l2b, 559 0) != 0) { 560 print_inode(value << l2b); 561 i_number = value; 562 last_op_type == TYPE_INODE; 563 } 564 } else if (strcmp((char *)$2, "d") == 0) { 565 if (verify_dent(i_number << l2b, 566 value) == 0) { 567 print_dent(i_number << l2b, 568 value); 569 d_entry = value; 570 last_op_type == TYPE_DIRENT; 571 } 572 } else { 573 fprintf(stdout, 574 gettext("Invalid command\n")); 575 } 576 } 577 ; 578 579 texpr : expr 580 { 581 value = $1; 582 count = 0; 583 } 584 | expr ',' expr 585 { 586 value = $1; 587 count = $3; 588 } 589 ; 590 591 expr : '+' 592 { 593 if (last_op_type == TYPE_INODE) { 594 if (verify_inode((i_number + 1) << l2b, 595 0) != 0) { 596 i_number ++; 597 print_inode(i_number << l2b); 598 $$ = i_number << l2b; 599 } 600 } else if (last_op_type == TYPE_DIRENT) { 601 if (verify_dent(i_number << l2b, 602 d_entry + 1) == 0) { 603 d_entry ++; 604 print_dent(i_number << l2b, 605 d_entry); 606 } 607 } else { 608 count = 0; $$ = value++; 609 } 610 } 611 | '-' 612 { 613 if (last_op_type == TYPE_INODE) { 614 if (verify_inode((i_number - 1) << l2b, 615 0) != 0) { 616 i_number --; 617 print_inode(i_number << l2b); 618 $$ = i_number << l2b; 619 } 620 } else if (last_op_type == TYPE_DIRENT) { 621 if (verify_dent(i_number << l2b, 622 d_entry - 1) == 0) { 623 d_entry --; 624 print_dent(i_number << l2b, 625 d_entry); 626 } 627 } else { 628 count = 0; $$ = value--; 629 } 630 } 631 | '-' WORD 632 { 633 uint64_t number; 634 635 if (check_and_get_int($2, &number) == 0) { 636 count = 0; 637 $$ = value - number; 638 } 639 } 640 | '+' WORD 641 { 642 uint64_t number; 643 644 if (check_and_get_int($2, &number) == 0) { 645 count = 0; 646 $$ = value + number; 647 } 648 } 649 | '*' WORD 650 { 651 uint64_t number; 652 653 if (check_and_get_int($2, &number) == 0) { 654 count = 0; 655 $$ = value * number; 656 } 657 } 658 | '%' WORD 659 { 660 uint64_t number; 661 662 if (check_and_get_int($2, &number) == 0) { 663 if (number == 0) { 664 fprintf(stdout, 665 gettext("Divide by zero ?\n")); 666 } else { 667 count = 0; 668 $$ = value / number; 669 } 670 } 671 } 672 | expr '-' expr { count = 0; $$ = $1 - $3; } 673 | expr '+' expr { count = 0; $$ = $1 + $3; } 674 | expr '*' expr { count = 0; $$ = $1 * $3; } 675 | expr '%' expr 676 { 677 if ($3 == 0) { 678 fprintf(stdout, 679 gettext("Divide by zero ?\n")); 680 } else { 681 $$ = $1 / $3; 682 } 683 count = 0; 684 } 685 | WORD 686 { 687 uint64_t number; 688 689 count = 0; 690 if (check_and_get_int($1, &number) == 0) { 691 $$ = number; 692 } 693 } 694 ; 695 696 %% 697 698 int32_t 699 check_and_get_int(uint8_t *str, uint64_t *value) 700 { 701 int32_t length, cbase, index, cvalue; 702 703 *value = 0; 704 length = strlen((caddr_t)str); 705 /* 706 * Decide on what base to be used 707 * and strip off the base specifier 708 */ 709 if ((str[0] == '0') && (str[1] == 'x')) { 710 cbase = 0x10; 711 index = 2; 712 } else if ((str[0] == '0') && (str[1] == 't')) { 713 cbase = 0xa; 714 index = 2; 715 } else if (str[0] == '0') { 716 cbase = 0x8; 717 index = 1; 718 } else { 719 cbase = base; 720 index = 0; 721 } 722 723 /* 724 * Verify if the string is integer 725 * and convert to a binary value 726 */ 727 for ( ; index < length; index++) { 728 if (cbase == 0x8) { 729 if ((str[index] < '0') || 730 (str[index] > '7')) { 731 fprintf(stdout, 732 gettext("Invalid Octal Number %s\n"), 733 str); 734 return (1); 735 } 736 cvalue = str[index] - '0'; 737 } else if (cbase == 0xa) { 738 if ((str[index] < '0') || 739 (str[index] > '9' )) { 740 fprintf(stdout, 741 gettext("Invalid Decimal Number %s\n"), 742 str); 743 return (1); 744 } 745 cvalue = str[index] - '0'; 746 } else { 747 if ((str[index] >= '0') && 748 (str[index] <= '9')) { 749 cvalue = str[index] - '0'; 750 } else if ((str[index] >= 'a') && 751 (str[index] <= 'f')) { 752 cvalue = str[index] - 'a' + 10; 753 } else if ((str[index] >= 'A') && 754 (str[index] <= 'F')) { 755 cvalue = str[index] - 'A' + 10; 756 } else { 757 fprintf(stdout, 758 gettext("Invalid Hex Number %s\n"), 759 str); 760 return (1); 761 } 762 } 763 *value = *value * cbase + cvalue; 764 } 765 return (0); 766 } 767 768 void print_prompt(); 769 extern FILE *yyin; 770 771 void 772 print_prompt() 773 { 774 fprintf(stdout, gettext("%s"), prompt); 775 } 776 777 int32_t 778 run_fsdb() 779 { 780 yyin = stdin; 781 if (yyparse() != 0) 782 return (-1); 783 return 0; 784 } 785