fsdb_yacc.y revision 7c478bd95313f5f23a4c958a745db2134aa03244
%{
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright (c) 1999-2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <locale.h>
#include <sys/param.h>
#include <sys/fs/udf_volume.h>
char shell_name[128] = "/bin/sh";
extern char prompt[];
extern uint16_t ricb_prn;
extern uint32_t ricb_loc;
extern int32_t bsize, bmask, l2d, l2b;
int base = 16;
int old_value = 0;
int value = 0;
int count = 0;
int last_op_type = 0;
#define TYPE_NONE 0
#define TYPE_INODE 1
#define TYPE_DIRENT 2
#define TYPE_BLOCK 3
#define TYPE_CD 4
uint32_t i_number = 0;
uint32_t d_entry = 0;
int error_override = 0;
int register_array[256];
char cwd[MAXPATHLEN] = "/";
int32_t ls_flags;
#define LONG_LIST 0x1
#define RECU_LIST 0x2
#define LIST_LS 0x4
int32_t find_flags;
#define FIND_DIR 0x1
#define FIND_NAME 0x2
#define FIND_INODE 0x4
#define FIND_DONE 0x8
char find_dir[1024];
char find_name[1024];
uint32_t find_in;
%}
%union
{
uint8_t *strval;
uint64_t intval;
};
%token BASE BLOCK CD DIRECTORY TFILE FIND FILL
%token INODE LS OVERRIDE PROMPT PWD QUIT TAG BANG
%token AVD MVDS RVDS INTS FSDS ROOT
%token ATTZ ATYE ATMO ATDA ATHO ATMI ATSE ATCE ATHU ATMIC
%token CTTZ CTYE CTMO CTDA CTHO CTMI CTSE CTCE CTHU CTMIC
%token MTTZ MTYE MTMO MTDA MTHO MTMI MTSE MTCE MTHU MTMIC
%token GID LN MD MAJ MIO NM SZ UID UNIQ
%token DOT
%token NL
%token WORD
%left '-' '+'
%left '*' '%'
%type <strval> WORD
%type <intval> expr
%%
session : statement_list
statement_list : /* empty */ { print_prompt(); }
| statement_list statement
{
ls_flags = 0;
}
;
statement : empty_statement
| current_value
| register
| base | block | cd | directory | file | find | fill
| inode | ls | override | nprompt | pwd | quit | tag | shell
| avd | mvds | rvds | ints | fsds | root
| at | ct | gid | ln | mt | md
| maj | min | nm | sz | uid | uniq
| dump | texpr
| error { yyclearin; yyerrok; }
;
empty_statement : NL
{
print_prompt();
}
;
current_value : DOT
{
if (last_op_type == TYPE_INODE) {
print_inode(i_number << l2b);
} else if (last_op_type == TYPE_DIRENT) {
print_dent(i_number << l2b, d_entry);
} else {
fprintf(stdout,
gettext("%x\n"), value);
}
}
;
register : '<' WORD
{
if ((strlen((caddr_t)$2) == 1) &&
((($2[0] >= 'a') &&
($2[0] <= 'z')) ||
(($2[0] >= 'A') &&
($2[0] <= 'Z')))) {
value = register_array[$2[0]];
} else {
fprintf(stdout,
gettext("Registers can"
" be only a-z or A-Z\n"));
}
}
| '>' WORD
{
if ((strlen((caddr_t)$2) == 1) &&
((($2[0] >= 'a') &&
($2[0] <= 'z')) ||
(($2[0] >= 'A') &&
($2[0] <= 'Z')))) {
register_array[$2[0]] = value;
} else {
fprintf(stdout,
gettext("Registers can"
" be only a-z or A-Z\n"));
}
}
;
base : BASE '=' expr
{
if (($3 == 8) || ($3 == 10) || ($3 == 16)) {
base = $3;
} else {
fprintf(stdout,
gettext("Requested %x Only"
" Oct, Dec and"
" Hex are Supported\n"), $3);
}
}
| BASE
{
fprintf(stdout,
gettext("Current Base in Decimal"
" : %d\n"), base);
}
;
block : BLOCK
{
last_op_type = TYPE_NONE;
value = value * DEV_BSIZE;
}
;
cd : CD ' ' WORD
{
uint8_t fl;
uint32_t temp;
char temp_cwd[MAXPATHLEN];
strcpy(temp_cwd, cwd);
if (strcmp((caddr_t)$3, "..") == 0) {
if (strlen(temp_cwd) == 1) {
if (temp_cwd[0] != '/') {
fprintf(stdout,
gettext("cwd is invalid"
"setting to /\n"));
strcpy(temp_cwd, "/");
}
} else {
dirname(temp_cwd);
}
} else {
int32_t len;
len = strlen(temp_cwd);
if (temp_cwd[len - 1] != '/') {
temp_cwd[len] = '/';
temp_cwd[len + 1] = '\0';
}
strcat(temp_cwd, (caddr_t)$3);
}
if (inode_from_path(temp_cwd, &temp,
&fl) != 0) {
fprintf(stdout,
gettext("Could not locate inode"
" for path %s\n"), temp_cwd);
strcpy(temp_cwd, "/");
if ((temp = ud_xlate_to_daddr(ricb_prn,
ricb_loc)) == 0) {
fprintf(stdout,
gettext("Failed to translate"
" prn %x loc %x\n"),
ricb_prn, ricb_loc);
}
} else {
if ((fl & FID_DIR) == 0) {
fprintf(stdout,
gettext("%s is not a"
" directory\n"), temp_cwd);
} else {
strcpy(cwd, temp_cwd);
value = temp << l2b;
last_op_type = TYPE_CD;
i_number = temp;
}
}
}
| CD
{
uint32_t block;
(void) strcpy(cwd, "/");
/*
* set current value to root icb
*/
if ((block = ud_xlate_to_daddr(ricb_prn,
ricb_loc)) == 0) {
fprintf(stdout,
gettext("Failed to translate "
"prn %x loc %x\n"),
ricb_prn, ricb_loc);
} else {
value = block << l2b;
last_op_type = TYPE_CD;
i_number = block;
}
}
;
directory : DIRECTORY
{
if (verify_dent(i_number << l2b, value) == 0) {
last_op_type = TYPE_DIRENT;
d_entry = value;
}
}
;
file : TFILE
{
}
;
find : xfind
{
if ((find_flags & (FIND_NAME | FIND_INODE)) &&
(find_flags & FIND_DONE)) {
if (find_dir[0] != '/') {
char buf[1024];
strcpy(buf, find_dir);
if ((strlen(cwd) == 1) &&
(cwd[0] == '/')) {
strcpy(find_dir, "/");
} else {
strcpy(find_dir, cwd);
strcat(find_dir, "/");
}
strcat(find_dir, buf);
}
find_it(find_dir, find_name, find_in,
(find_flags & (FIND_NAME | FIND_INODE)));
}
find_flags = 0;
find_dir[0] = '\0';
find_name[0] = '\0';
find_in = 0;
}
;
xfind : FIND WORD
{
strcpy(find_dir, (char *)$2);
find_flags = FIND_DIR;
}
| xfind ' ' WORD
{
if (find_flags == FIND_DIR) {
if (strcmp((char *)$3, "-name") == 0) {
find_flags = FIND_NAME;
} else if (strcmp((char *)$3, "-inum")
== 0) {
find_flags = FIND_INODE;
} else {
fprintf(stdout,
gettext("find dir-name {-name n | -inum n}\n"));
}
} else if (find_flags == FIND_NAME) {
strcpy(find_name, (char *)$3);
find_flags |= FIND_DONE;
} else if (find_flags == FIND_INODE) {
uint64_t temp;
if (check_and_get_int($3, &temp) ==
0) {
find_in = temp;
find_flags |= FIND_DONE;
} else {
fprintf(stdout,
gettext("find dir-name {-name n | -inum n}\n"));
}
} else {
fprintf(stdout,
gettext("find dir-name {-name n | -inum n}\n"));
}
}
| xfind ' ' expr
{
if (find_flags == FIND_INODE) {
find_in = $3;
find_flags |= FIND_DONE;
} else {
fprintf(stdout,
gettext("find dir-name {-name n | -inum n}\n"));
}
}
;
fill : FILL '=' WORD
{
fill_pattern(value, count, $3);
}
;
inode : INODE
{
uint32_t temp;
if (last_op_type == TYPE_CD) {
temp = value;
} else {
temp = value << l2b;
}
last_op_type = TYPE_INODE;
if (verify_inode(temp, 0) != 0) {
i_number = temp >> l2b;
d_entry = 0;
}
}
;
ls : xls
{
if (ls_flags & LIST_LS) {
list(".", i_number, ls_flags);
}
}
;
xls : LS
{
/* Do nothing */
ls_flags = LIST_LS;
}
| xls ' ' WORD
{
if (strcmp((caddr_t)$3, "-l") == 0) {
ls_flags |= LONG_LIST;
} else if (strcmp((caddr_t)$3, "-R") == 0) {
ls_flags |= RECU_LIST;
} else if ((strcmp((caddr_t)$3, "-lR") == 0) ||
(strcmp((caddr_t)$3, "-Rl") == 0)) {
ls_flags |= LONG_LIST | RECU_LIST;
} else {
list(".", i_number, ls_flags);
ls_flags &= ~LIST_LS;
}
}
;
override : OVERRIDE
{
if (error_override == 0) {
error_override = 1;
(void) fprintf(stdout,
gettext("error checking on\n"));
} else {
error_override = 0;
(void) fprintf(stdout,
gettext("error checking off\n"));
}
}
;
nprompt : PROMPT '=' WORD
{
(void) strcpy(prompt, (caddr_t)$3);
}
;
pwd : PWD
{
fprintf(stdout, gettext("%s\n"), cwd);
}
;
quit : QUIT
{
exit (0);
}
;
tag : TAG
{
print_desc(value, 0);
}
;
shell : BANG
{
system(shell_name);
}
;
avd : AVD { print_desc(NULL, AVD); }
;
mvds : MVDS { print_desc(NULL, MVDS); }
;
rvds : RVDS { print_desc(NULL, RVDS); }
;
ints : INTS { print_desc(NULL, INTS); }
;
fsds : FSDS { print_desc(NULL, FSDS); }
;
root : ROOT { print_desc(NULL, ROOT); }
;
at : ATTZ '=' expr { set_file(ATTZ, i_number << l2b, $3); }
| ATYE '=' expr { set_file(ATYE, i_number << l2b, $3); }
| ATMO '=' expr { set_file(ATMO, i_number << l2b, $3); }
| ATDA '=' expr { set_file(ATDA, i_number << l2b, $3); }
| ATHO '=' expr { set_file(ATHO, i_number << l2b, $3); }
| ATMI '=' expr { set_file(ATMI, i_number << l2b, $3); }
| ATSE '=' expr { set_file(ATSE, i_number << l2b, $3); }
| ATCE '=' expr { set_file(ATCE, i_number << l2b, $3); }
| ATHU '=' expr { set_file(ATHU, i_number << l2b, $3); }
| ATMIC '=' expr
{
set_file(ATMIC, i_number << l2b, $3);
}
;
ct : CTTZ '=' expr { set_file(CTTZ, i_number << l2b, $3); }
| CTYE '=' expr { set_file(CTYE, i_number << l2b, $3); }
| CTMO '=' expr { set_file(CTMO, i_number << l2b, $3); }
| CTDA '=' expr { set_file(CTDA, i_number << l2b, $3); }
| CTHO '=' expr { set_file(CTHO, i_number << l2b, $3); }
| CTMI '=' expr { set_file(CTMI, i_number << l2b, $3); }
| CTSE '=' expr { set_file(CTSE, i_number << l2b, $3); }
| CTCE '=' expr { set_file(CTCE, i_number << l2b, $3); }
| CTHU '=' expr { set_file(CTHU, i_number << l2b, $3); }
| CTMIC '=' expr
{
set_file(CTMIC, i_number << l2b, $3);
}
;
mt : MTTZ '=' expr { set_file(MTTZ, i_number << l2b, $3); }
| MTYE '=' expr { set_file(MTYE, i_number << l2b, $3); }
| MTMO '=' expr { set_file(MTMO, i_number << l2b, $3); }
| MTDA '=' expr { set_file(MTDA, i_number << l2b, $3); }
| MTHO '=' expr { set_file(MTHO, i_number << l2b, $3); }
| MTMI '=' expr { set_file(MTMI, i_number << l2b, $3); }
| MTSE '=' expr { set_file(MTSE, i_number << l2b, $3); }
| MTCE '=' expr { set_file(MTCE, i_number << l2b, $3); }
| MTHU '=' expr { set_file(MTHU, i_number << l2b, $3); }
| MTMIC '=' expr
{
set_file(MTMIC, i_number << l2b, $3);
}
;
gid : GID '=' expr { set_file(GID, i_number << l2b, $3); }
;
ln : LN '=' expr { set_file(LN, i_number << l2b, $3); }
;
md : MD '=' expr { set_file(MD, i_number << l2b, $3); }
;
maj : MAJ '=' expr { set_file(MAJ, i_number << l2b, $3); }
;
min : MIO '=' expr { set_file(MIO, i_number << l2b, $3); }
;
nm : NM '=' expr { set_file(NM, i_number << l2b, $3); }
;
sz : SZ '=' expr { set_file(SZ, i_number << l2b, $3); }
;
uid : UID '=' expr { set_file(UID, i_number << l2b, $3); }
;
uniq : UNIQ '=' expr { set_file(UNIQ, i_number << l2b, $3); }
;
dump : '/' WORD
{
if (strlen((char *)$2) != 1) {
fprintf(stdout,
gettext("Invalid command\n"));
} else {
dump_disk(value, count, $2);
}
}
| '?' WORD
{
if (strcmp((char *)$2, "i") == 0) {
if (verify_inode(value << l2b,
0) != 0) {
print_inode(value << l2b);
i_number = value;
last_op_type == TYPE_INODE;
}
} else if (strcmp((char *)$2, "d") == 0) {
if (verify_dent(i_number << l2b,
value) == 0) {
print_dent(i_number << l2b,
value);
d_entry = value;
last_op_type == TYPE_DIRENT;
}
} else {
fprintf(stdout,
gettext("Invalid command\n"));
}
}
;
texpr : expr
{
value = $1;
count = 0;
}
| expr ',' expr
{
value = $1;
count = $3;
}
;
expr : '+'
{
if (last_op_type == TYPE_INODE) {
if (verify_inode((i_number + 1) << l2b,
0) != 0) {
i_number ++;
print_inode(i_number << l2b);
$$ = i_number << l2b;
}
} else if (last_op_type == TYPE_DIRENT) {
if (verify_dent(i_number << l2b,
d_entry + 1) == 0) {
d_entry ++;
print_dent(i_number << l2b,
d_entry);
}
} else {
count = 0; $$ = value++;
}
}
| '-'
{
if (last_op_type == TYPE_INODE) {
if (verify_inode((i_number - 1) << l2b,
0) != 0) {
i_number --;
print_inode(i_number << l2b);
$$ = i_number << l2b;
}
} else if (last_op_type == TYPE_DIRENT) {
if (verify_dent(i_number << l2b,
d_entry - 1) == 0) {
d_entry --;
print_dent(i_number << l2b,
d_entry);
}
} else {
count = 0; $$ = value--;
}
}
| '-' WORD
{
uint64_t number;
if (check_and_get_int($2, &number) == 0) {
count = 0;
$$ = value - number;
}
}
| '+' WORD
{
uint64_t number;
if (check_and_get_int($2, &number) == 0) {
count = 0;
$$ = value + number;
}
}
| '*' WORD
{
uint64_t number;
if (check_and_get_int($2, &number) == 0) {
count = 0;
$$ = value * number;
}
}
| '%' WORD
{
uint64_t number;
if (check_and_get_int($2, &number) == 0) {
if (number == 0) {
fprintf(stdout,
gettext("Divide by zero ?\n"));
} else {
count = 0;
$$ = value / number;
}
}
}
| expr '-' expr { count = 0; $$ = $1 - $3; }
| expr '+' expr { count = 0; $$ = $1 + $3; }
| expr '*' expr { count = 0; $$ = $1 * $3; }
| expr '%' expr
{
if ($3 == 0) {
fprintf(stdout,
gettext("Divide by zero ?\n"));
} else {
$$ = $1 / $3;
}
count = 0;
}
| WORD
{
uint64_t number;
count = 0;
if (check_and_get_int($1, &number) == 0) {
$$ = number;
}
}
;
%%
int32_t
check_and_get_int(uint8_t *str, uint64_t *value)
{
int32_t length, cbase, index, cvalue;
*value = 0;
length = strlen((caddr_t)str);
/*
* Decide on what base to be used
* and strip off the base specifier
*/
if ((str[0] == '0') && (str[1] == 'x')) {
cbase = 0x10;
index = 2;
} else if ((str[0] == '0') && (str[1] == 't')) {
cbase = 0xa;
index = 2;
} else if (str[0] == '0') {
cbase = 0x8;
index = 1;
} else {
cbase = base;
index = 0;
}
/*
* Verify if the string is integer
* and convert to a binary value
*/
for ( ; index < length; index++) {
if (cbase == 0x8) {
if ((str[index] < '0') ||
(str[index] > '7')) {
fprintf(stdout,
gettext("Invalid Octal Number %s\n"),
str);
return (1);
}
cvalue = str[index] - '0';
} else if (cbase == 0xa) {
if ((str[index] < '0') ||
(str[index] > '9' )) {
fprintf(stdout,
gettext("Invalid Decimal Number %s\n"),
str);
return (1);
}
cvalue = str[index] - '0';
} else {
if ((str[index] >= '0') &&
(str[index] <= '9')) {
cvalue = str[index] - '0';
} else if ((str[index] >= 'a') &&
(str[index] <= 'f')) {
cvalue = str[index] - 'a' + 10;
} else if ((str[index] >= 'A') &&
(str[index] <= 'F')) {
cvalue = str[index] - 'A' + 10;
} else {
fprintf(stdout,
gettext("Invalid Hex Number %s\n"),
str);
return (1);
}
}
*value = *value * cbase + cvalue;
}
return (0);
}
void print_prompt();
extern FILE *yyin;
void
print_prompt()
{
fprintf(stdout, gettext("%s"), prompt);
}
int32_t
run_fsdb()
{
yyin = stdin;
if (yyparse() != 0)
return (-1);
return 0;
}