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
print_prompt()774 print_prompt()
775 {
776 fprintf(stdout, gettext("%s"), prompt);
777 }
778
779 int32_t
run_fsdb()780 run_fsdb()
781 {
782 yyin = stdin;
783 if (yyparse() != 0)
784 return (-1);
785 return 0;
786 }
787