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