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