# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright (c) 2018, Joyent, Inc. # FSTYPE= udfs LIBPROG= fsdb include ../../Makefile.fstype # fsdb has a name clash with main() and libl.so.1. However, fsdb must # still export a number of "yy*" (libl) interfaces. Reduce all other symbols # to local scope. MAPFILES += $(MAPFILE.INT) $(MAPFILE.LEX) $(MAPFILE.NGB) MAPOPTS = $(MAPFILES:%=-Wl,-M%) CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 CPPFLAGS += -I../common LDLIBS += -lmalloc -ll -ladm LDFLAGS += $(MAPOPTS) YFLAGS = "-d" CERRWARN += -Wno-implicit-function-declaration CERRWARN += -Wno-unused-variable CERRWARN += -Wno-unused-value CERRWARN += -Wno-unused-function # Hammerhead: Suppress pointer/int cast warnings in legacy UDFS code CERRWARN += -Wno-pointer-to-int-cast CERRWARN += -Wno-int-to-pointer-cast # because of labels from yacc fsdb_yacc.o fsdb_lex.o : CERRWARN += -Wno-unused-label # not linted SMATCH=off SRCS= fsdb.c ../common/ud_lib.c fsdb : fsdb_yacc.o fsdb_lex.o ud_lib.o fsdb.o $(MAPFILES) $(LINK.c) -o $@ fsdb.o fsdb_yacc.o fsdb_lex.o \ ud_lib.o $(LDLIBS) $(POST_PROCESS) fsdb.o : fsdb.c $(COMPILE.c) -o $@ fsdb.c $(POST_PROCESS_O) ud_lib.o : ../common/ud_lib.c ../common/ud_lib.h $(COMPILE.c) -o $@ ../common/ud_lib.c $(POST_PROCESS_O) y.tab.c : fsdb_yacc.y $(YACC.y) fsdb_yacc.y fsdb_yacc.o : y.tab.c $(COMPILE.c) -o $@ y.tab.c $(POST_PROCESS_O) lex.yy.c : fsdb_lex.l $(LEX) -e fsdb_lex.l fsdb_lex.o : lex.yy.c $(COMPILE.c) -o $@ lex.yy.c $(POST_PROCESS_O) clean : $(RM) fsdb.o ud_lib.o fsdb_yacc.o fsdb_lex.o $(RM) fsdb_yacc.c fsdb_lex.c y.tab.c y.tab.h lex.yy.c # for messaging catalog # POFILE= fsdb.po # for messaging catalog # catalog: $(POFILE) CATSRCS= $(SRCS) lex.yy.c y.tab.c $(POFILE): $(CATSRCS) ../common/ud_lib.h $(RM) $@ $(COMPILE.cpp) $(CATSRCS) > $(POFILE).i $(XGETTEXT) $(XGETFLAGS) $(POFILE).i $(SED) "/^domain/d" messages.po > $@ $(RM) $(POFILE).i messages.po /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ud_lib.h" #include "y.tab.h" typedef unsigned short unicode_t; #define MAXNAMLEN 0x200 extern uint32_t i_number; extern int32_t run_fsdb(); void usage(); void init_buffers(); char *getblk(u_offset_t); int32_t parse_udfs(uint32_t); int32_t parse_vds(uint32_t, uint32_t); int32_t parse_part(struct part_desc *); int32_t parse_lvd(struct log_vol_desc *); int32_t parse_fsds(); int32_t get_vat_loc(); int32_t get_fid(uint32_t, uint8_t *, uint64_t); char *progname; char prompt[256] = "fsdb>"; #define ARG_OVERRIDE 0 #define ARG_NEW_PROMPT 1 #define ARG_WR_ENABLED 2 #define ARG_USAGE 3 char *subopt_v[] = { "o", "p", "w", "?", NULL }; int32_t override = 0; int32_t openflg = O_RDONLY; #define MAX_PARTS 10 /* * udp_flags */ #define UDP_BITMAPS 0x00 #define UDP_SPACETBLS 0x01 ud_handle_t udh; int32_t fd, nparts, nmaps; int32_t bmask, l2d, l2b; uint16_t ricb_prn; uint32_t ricb_loc, ricb_len; extern int value; int32_t main(int argc, char *argv[]) { int opt, ret; uint32_t bsize; char *subopts, *optval; #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); progname = argv[0]; while ((opt = getopt(argc, argv, "o:")) != EOF) { switch (opt) { case 'o' : subopts = optarg; while (*subopts != '\0') { switch (getsubopt(&subopts, subopt_v, &optval)) { case ARG_OVERRIDE : override = 1; (void) fprintf(stdout, gettext("error checking off\n")); break; case ARG_NEW_PROMPT : if (optval == NULL) { usage(); } if (strlen(optval) > 255) { (void) fprintf(stdout, gettext("prompt should be less" "than 255 bytes\n")); exit(1); } (void) strcpy(prompt, optval); break; case ARG_WR_ENABLED : openflg = O_RDWR; break; case ARG_USAGE : default : usage(); } } break; default : usage(); } } if ((argc - optind) != 1) { /* Should just have "special" left */ usage(); } if (ud_init(-1, &udh) != 0) { (void) fprintf(stderr, gettext("udfs labelit: cannot initialize ud_lib\n")); exit(1); } if ((fd = ud_open_dev(udh, argv[optind], openflg)) < 0) { perror("open"); exit(1); } if ((ret = ud_fill_udfs_info(udh)) != 0) { return (ret); } if ((udh->udfs.flags & VALID_UDFS) == 0) { return (1); } bsize = udh->udfs.lbsize; bmask = bsize - 1; l2d = 0; while ((bsize >> l2d) > DEV_BSIZE) { l2d++; } l2b = l2d + 9; ricb_prn = udh->udfs.ricb_prn; ricb_loc = udh->udfs.ricb_loc; ricb_len = udh->udfs.ricb_len; value = i_number = ud_xlate_to_daddr(udh, ricb_prn, ricb_loc); init_buffers(); run_fsdb(); ud_fini(udh); (void) close(fd); return (0); } /* * usage - print usage and exit */ void usage() { (void) fprintf(stdout, gettext("usage: %s [options] special\n"), progname); (void) fprintf(stdout, gettext("options:\n")); (void) fprintf(stdout, gettext("\t-o\tSpecify udfs filesystem sepcific options\n")); (void) fprintf(stdout, gettext("\t\tAvailable suboptions are:\n")); (void) fprintf(stdout, gettext("\t\t?\tdisplay usage\n")); (void) fprintf(stdout, gettext("\t\to\toverride some error conditions\n")); (void) fprintf(stdout, gettext("\t\tp\t\"string\" set prompt to string\n")); (void) fprintf(stdout, gettext("\t\tw\topen for write\n")); exit(1); } #define NBUF 10 static struct lbuf { struct lbuf *fwd; struct lbuf *back; int32_t valid; char *blkaddr; u_offset_t blkno; } lbuf[NBUF], bhdr; #define INSERT(bp) \ { \ bp->back = &bhdr; \ bp->fwd = bhdr.fwd; \ bhdr.fwd->back = bp; \ bhdr.fwd = bp; \ } void init_buffers() { int32_t i; char *addr; struct lbuf *bp; addr = malloc(NBUF * udh->udfs.lbsize); bhdr.fwd = bhdr.back = &bhdr; for (i = 0; i < NBUF; i++) { bp = &lbuf[i]; bp->blkaddr = addr + i * udh->udfs.lbsize; bp->valid = 0; INSERT(bp); } } char * getblk(u_offset_t address) { u_offset_t off, block; struct lbuf *bp; off = address & ~bmask; block = address >> l2b; for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) { if (bp->valid && bp->blkno == block) { goto found; } } bp = bhdr.back; bp->blkno = block; bp->valid = 0; errno = 0; if (llseek(fd, off, SEEK_SET) != off) { (void) fprintf(stdout, gettext("Seek failed fd %x off %llx errno %x\n"), fd, off, errno); return (NULL); } errno = 0; if (read(fd, bp->blkaddr, udh->udfs.lbsize) != udh->udfs.lbsize) { (void) fprintf(stdout, gettext("Read failed fd %x off %llx errno %x\n"), fd, off, errno); return (NULL); } bp->valid = 1; found: bp->back->fwd = bp->fwd; bp->fwd->back = bp->back; INSERT(bp); return (bp->blkaddr); } int32_t putblk(caddr_t address) { u_offset_t off; struct lbuf *bp; if (openflg == O_RDONLY) { (void) fprintf(stdout, gettext("Not run with -w flag\n")); return (1); } for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) { if (bp->valid && bp->blkaddr == address) { goto found; } } (void) fprintf(stdout, gettext("Could not find the buffer\n")); return (1); found: off = bp->blkno << l2b; if (llseek(fd, off, SEEK_SET) == off) { if (write(fd, bp->blkaddr, udh->udfs.lbsize) == udh->udfs.lbsize) { return (0); } (void) fprintf(stdout, gettext("Write failed fd %x off %llx errno %x\n"), fd, off, errno); } else { (void) fprintf(stdout, gettext("Seek failed fd %x off %llx errno %x\n"), fd, off, errno); } return (1); } void inval_bufs() { struct lbuf *bp; for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) { bp->valid = 0; } } /* * If addr == NULL then use id to print the desc * other wise use addr to self identify the type of desc */ void print_desc(uint32_t addr, int32_t id) { struct tag *tag; caddr_t baddr; /* * Read the block at addr * find out the type of tag * and print the descriptor */ if (addr != 0) { if ((baddr = getblk(addr & (~bmask))) == NULL) { (void) fprintf(stdout, gettext("Could not read block %x\n"), addr >> l2b); } /* LINTED */ tag = (struct tag *)(baddr + (addr & bmask)); } else { switch (id) { case AVD : /* LINTED */ if ((tag = (struct tag *)getblk( udh->udfs.avdp_loc << l2b)) == NULL) { (void) fprintf(stdout, gettext("Could not read AVDP\n")); } break; case MVDS : case RVDS : case INTS : { uint32_t i, end; if (id == MVDS) { i = udh->udfs.mvds_loc; end = i + (udh->udfs.mvds_len >> l2b); } else if (id == RVDS) { i = udh->udfs.rvds_loc; end = i + (udh->udfs.rvds_len >> l2b); } else { i = udh->udfs.lvid_loc; end = i + (udh->udfs.lvid_len >> l2b); } for (; i < end; i++) { print_desc(i << l2b, 0); } } return; case FSDS : case ROOT : { uint16_t prn; uint32_t i, end, block; if (id == FSDS) { prn = udh->udfs.fsds_prn; i = udh->udfs.fsds_loc; end = i + (udh->udfs.fsds_len >> l2b); } else { prn = ricb_prn; i = ricb_loc; end = i + (ricb_len >> l2b); } for (; i < end; i++) { if ((block = ud_xlate_to_daddr( udh, prn, i)) == 0) { (void) fprintf(stdout, gettext("Cannot xlate " "prn %x loc %x\n"), prn, i); continue; } print_desc(block << l2b, 0); } } /* FALLTHROUGH */ default : return; } } switch (SWAP_16(tag->tag_id)) { case UD_PRI_VOL_DESC : print_pvd(stdout, (struct pri_vol_desc *)tag); break; case UD_ANCH_VOL_DESC : print_avd(stdout, (struct anch_vol_desc_ptr *)tag); break; case UD_VOL_DESC_PTR : print_vdp(stdout, (struct vol_desc_ptr *)tag); break; case UD_IMPL_USE_DESC : print_iuvd(stdout, (struct iuvd_desc *)tag); break; case UD_PART_DESC : print_part(stdout, (struct part_desc *)tag); break; case UD_LOG_VOL_DESC : print_lvd(stdout, (struct log_vol_desc *)tag); break; case UD_UNALL_SPA_DESC : print_usd(stdout, (struct unall_spc_desc *)tag); break; case UD_TERM_DESC : (void) fprintf(stdout, "TERM DESC\n"); print_tag(stdout, tag); break; case UD_LOG_VOL_INT : print_lvid(stdout, (struct log_vol_int_desc *)tag); break; case UD_FILE_SET_DESC : print_fsd(stdout, udh, (struct file_set_desc *)tag); break; case UD_FILE_ID_DESC : print_fid(stdout, (struct file_id *)tag); break; case UD_ALLOC_EXT_DESC : print_aed(stdout, (struct alloc_ext_desc *)tag); break; case UD_INDIRECT_ENT : print_ie(stdout, (struct indirect_entry *)tag); break; case UD_TERMINAL_ENT : print_td(stdout, (struct term_desc *)tag); break; case UD_FILE_ENTRY : print_fe(stdout, (struct file_entry *)tag); break; case UD_EXT_ATTR_HDR : case UD_UNALL_SPA_ENT : case UD_SPA_BMAP_DESC : case UD_PART_INT_DESC : case UD_EXT_FILE_ENT : break; default : (void) fprintf(stdout, gettext("unknown descriptor\n")); print_tag(stdout, tag); break; } } void set_file(int32_t id, uint32_t iloc, uint64_t value) { uint8_t i8; uint16_t i16; uint32_t i32, block, ea_len, ea_off; uint64_t i64; struct file_entry *fe; struct dev_spec_ear *ds; struct attr_hdr *ah; struct ext_attr_hdr *eah; /* LINTED */ if ((fe = (struct file_entry *)getblk(iloc)) == NULL) { return; } if (ud_verify_tag(udh, &fe->fe_tag, UD_FILE_ENTRY, SWAP_32(fe->fe_tag.tag_loc), 1, 1) != 0) { return; } i8 = (uint8_t)value; i16 = SWAP_16(((uint16_t)value)); i32 = SWAP_32(((uint32_t)value)); i64 = SWAP_64(value); switch (id) { case ATTZ : fe->fe_acc_time.ts_tzone = i16; break; case ATYE : fe->fe_acc_time.ts_year = i16; break; case ATMO : fe->fe_acc_time.ts_month = i8; break; case ATDA : fe->fe_acc_time.ts_day = i8; break; case ATHO : fe->fe_acc_time.ts_hour = i8; break; case ATMI : fe->fe_acc_time.ts_min = i8; break; case ATSE : fe->fe_acc_time.ts_sec = i8; break; case ATCE : fe->fe_acc_time.ts_csec = i8; break; case ATHU : fe->fe_acc_time.ts_husec = i8; break; case ATMIC : fe->fe_acc_time.ts_usec = i8; break; case CTTZ : fe->fe_attr_time.ts_tzone = i16; break; case CTYE : fe->fe_attr_time.ts_year = i16; break; case CTMO : fe->fe_attr_time.ts_month = i8; break; case CTDA : fe->fe_attr_time.ts_day = i8; break; case CTHO : fe->fe_attr_time.ts_hour = i8; break; case CTMI : fe->fe_attr_time.ts_min = i8; break; case CTSE : fe->fe_attr_time.ts_sec = i8; break; case CTCE : fe->fe_attr_time.ts_csec = i8; break; case CTHU : fe->fe_attr_time.ts_husec = i8; break; case CTMIC : fe->fe_attr_time.ts_usec = i8; break; case MTTZ : fe->fe_mod_time.ts_tzone = i16; break; case MTYE : fe->fe_mod_time.ts_year = i16; break; case MTMO : fe->fe_mod_time.ts_month = i8; break; case MTDA : fe->fe_mod_time.ts_day = i8; break; case MTHO : fe->fe_mod_time.ts_hour = i8; break; case MTMI : fe->fe_mod_time.ts_min = i8; break; case MTSE : fe->fe_mod_time.ts_sec = i8; break; case MTCE : fe->fe_mod_time.ts_csec = i8; break; case MTHU : fe->fe_mod_time.ts_husec = i8; break; case MTMIC : fe->fe_mod_time.ts_usec = i8; break; case GID : fe->fe_gid = i32; break; case LN : fe->fe_lcount = i16; break; case MD : fe->fe_perms = i32; break; case MAJ : case MIO : if ((fe->fe_icb_tag.itag_ftype != VBLK) && (fe->fe_icb_tag.itag_ftype != VCHR)) { (void) fprintf(stdout, gettext("Not a device\n")); break; } /* LINTED */ eah = (struct ext_attr_hdr *)fe->fe_spec; ea_off = SWAP_32(eah->eah_ial); ea_len = SWAP_32(fe->fe_len_ear); block = SWAP_32(eah->eah_tag.tag_loc); if (ea_len && (ud_verify_tag(udh, &eah->eah_tag, UD_EXT_ATTR_HDR, block, 1, 1) == 0)) { while (ea_off < ea_len) { /* LINTED */ ah = (struct attr_hdr *) &fe->fe_spec[ea_off]; if ((ah->ahdr_atype == SWAP_32(12)) && (ah->ahdr_astype == 1)) { ds = (struct dev_spec_ear *)ah; if (id == MAJ) { ds->ds_major_id = i32; } else { ds->ds_minor_id = i32; } ud_make_tag(udh, &eah->eah_tag, UD_EXT_ATTR_HDR, block, eah->eah_tag.tag_crc_len); break; } } } (void) fprintf(stdout, gettext("does not have a Device Specification EA\n")); break; case NM : break; case SZ : fe->fe_info_len = i64; break; case UID : fe->fe_uid = i32; break; case UNIQ : fe->fe_uniq_id = i32; break; default : (void) fprintf(stdout, gettext("Unknown set\n")); } ud_make_tag(udh, &fe->fe_tag, UD_FILE_ENTRY, SWAP_32(fe->fe_tag.tag_loc), fe->fe_tag.tag_crc_len); (void) putblk((caddr_t)fe); } caddr_t verify_inode(uint32_t addr, uint32_t type) { struct file_entry *fe; struct tag *tag; /* LINTED */ if ((tag = (struct tag *)getblk(addr & (~bmask))) == NULL) { (void) fprintf(stdout, gettext("Could not read block %x\n"), addr >> l2b); } else { if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, addr >> l2b, 0, 1) != 0) { (void) fprintf(stdout, gettext("Not a file entry(inode) at %x\n"), addr >> l2b); } else { if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, SWAP_32(tag->tag_loc), 1, 1) != 0) { (void) fprintf(stdout, gettext("CRC failed\n")); } else { fe = (struct file_entry *)tag; if ((type == 0) || (type == fe->fe_icb_tag.itag_ftype)) { return ((caddr_t)tag); } } } } return (0); } void print_inode(uint32_t addr) { if (verify_inode(addr, 0) != NULL) { print_desc(addr, 0); } } int32_t verify_dent(uint32_t i_addr, uint32_t nent) { uint32_t ent = 0; uint64_t off = 0; uint8_t buf[1024]; struct file_id *fid; /* LINTED */ fid = (struct file_id *)buf; if (verify_inode(i_addr, 4) == 0) { (void) fprintf(stdout, gettext("Inode is not a directory\n")); return (1); } while (get_fid(i_addr >> l2b, buf, off) == 0) { off += FID_LEN(fid); if (ent == nent) { return (0); } ent++; } (void) fprintf(stdout, gettext("Reached EOF\n")); return (1); } void print_dent(uint32_t i_addr, uint32_t nent) { uint32_t ent = 0; uint64_t off = 0; uint8_t buf[1024]; struct file_id *fid; /* LINTED */ fid = (struct file_id *)buf; if (verify_dent(i_addr, nent) == 0) { while (get_fid(i_addr >> l2b, buf, off) == 0) { off += FID_LEN(fid); if (ent == nent) { print_fid(stdout, fid); return; } ent++; } } } uint32_t in; uint32_t de_count, ie_count; struct ext { uint16_t prn; uint16_t flags; uint32_t blkno; uint32_t len; } *de, *ie; int32_t get_blkno(uint32_t inode, uint32_t *blkno, uint64_t off) { struct file_entry *fe; int32_t i, d, nent; uint16_t prn, flags, elen; uint32_t desc_type, bno, len; struct short_ad *sad; struct long_ad *lad; uint64_t b_off, e_off; if (inode != in) { /* LINTED */ if ((fe = (struct file_entry *) getblk(inode << l2b)) == NULL) { (void) fprintf(stdout, gettext("Could not read block %x\n"), off & (~bmask)); return (1); } desc_type = SWAP_16(fe->fe_icb_tag.itag_flags) & 0x7; sad = NULL; lad = NULL; if (desc_type == ICB_FLAG_SHORT_AD) { elen = sizeof (struct short_ad); /* LINTED */ sad = (struct short_ad *) (fe->fe_spec + SWAP_32(fe->fe_len_ear)); } else if (desc_type == ICB_FLAG_LONG_AD) { elen = sizeof (struct long_ad); /* LINTED */ lad = (struct long_ad *) (fe->fe_spec + SWAP_32(fe->fe_len_ear)); } else if (desc_type == ICB_FLAG_ONE_AD) { *blkno = inode; return (0); } else { /* This cannot happen return */ return (EINVAL); } nent = SWAP_32(fe->fe_len_adesc) / elen; de = malloc(nent * sizeof (struct ext)); if (de == NULL) { (void) fprintf(stdout, gettext("could not allocate memeory\n")); return (1); } in = inode; de_count = nent; for (d = 0, i = 0; i < nent; i++) { switch (desc_type) { case ICB_FLAG_SHORT_AD: prn = 0; bno = SWAP_32(sad->sad_ext_loc); len = SWAP_32(sad->sad_ext_len); break; case ICB_FLAG_LONG_AD: prn = SWAP_16(lad->lad_ext_prn); bno = SWAP_32(lad->lad_ext_loc); len = SWAP_32(lad->lad_ext_len); break; default: prn = 0; bno = 0; len = 0; } flags = len >> 30; if (flags == 0x3) { (void) fprintf(stdout, gettext("Handle IE\n")); } else { de[d].prn = prn; de[d].flags = flags; de[d].blkno = bno; de[d].len = len & 0x3FFFFFFF; d++; } } } b_off = 0; for (i = 0; i < de_count; i++) { e_off = b_off + de[i].len; if (off < e_off) { bno = de[i].blkno + ((off - b_off) >> l2b); if ((*blkno = ud_xlate_to_daddr( udh, de[i].prn, bno)) == 0) { return (1); } return (0); } b_off = e_off; } return (1); } /* * assume the buffer is big enough * for the entire request */ int32_t read_file(uint32_t inode, uint8_t *buf, uint32_t count, uint64_t off) { caddr_t addr; uint32_t bno, tcount; while (count) { if (get_blkno(inode, &bno, off) != 0) { return (1); } if ((addr = getblk(bno << l2b)) == NULL) { return (1); } if (bno == inode) { struct file_entry *fe; /* * embedded file */ /* LINTED */ fe = (struct file_entry *)addr; addr += 0xB0 + SWAP_32(fe->fe_len_ear); if (off >= SWAP_64(fe->fe_info_len)) { return (1); } } tcount = udh->udfs.lbsize - (off & bmask); if (tcount > count) { tcount = count; } addr += off & bmask; (void) memcpy(buf, addr, tcount); count -= tcount; buf += tcount; off += tcount; } return (0); } int32_t get_fid(uint32_t inode, uint8_t *buf, uint64_t off) { struct file_id *fid; /* LINTED */ fid = (struct file_id *)buf; if ((read_file(inode, buf, sizeof (struct file_id), off)) != 0) { return (1); } if (ud_verify_tag(udh, &fid->fid_tag, UD_FILE_ID_DESC, 0, 0, 1) != 0) { (void) fprintf(stdout, gettext("file_id tag does not verify off %llx\n"), off); return (1); } if ((read_file(inode, buf, FID_LEN(fid), off)) != 0) { return (1); } return (0); } /* * Path is absolute path */ int32_t inode_from_path(char *path, uint32_t *in, uint8_t *fl) { char dname[1024]; char fname[256]; int32_t err; uint32_t dinode; struct tag *tag; uint8_t flags; uint8_t buf[1024]; uint64_t off; struct file_id *fid; uint8_t *addr; if (strcmp(path, "/") == 0) { *fl = FID_DIR; if ((*in = ud_xlate_to_daddr(udh, ricb_prn, ricb_loc)) == 0) { return (1); } return (0); } (void) strcpy(dname, path); (void) strcpy(fname, basename(dname)); (void) dirname(dname); if ((err = inode_from_path(dname, &dinode, &flags)) != 0) { return (1); } /* * Check if dname is a directory */ if ((flags & FID_DIR) == 0) { (void) fprintf(stdout, gettext("Path %s is not a directory\n"), path); } /* * Search for the fname in the directory now */ off = 0; /* LINTED */ fid = (struct file_id *)buf; while (get_fid(dinode, buf, off) == 0) { off += FID_LEN(fid); if (fid->fid_flags & FID_DELETED) { continue; } addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; if (fid->fid_flags & FID_PARENT) { addr[0] = '.'; addr[1] = '.'; addr[2] = '\0'; } else { addr[fid->fid_idlen] = '\0'; } if (strcmp((caddr_t)addr, fname) == 0) { *fl = fid->fid_flags; if ((*in = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn), SWAP_32(fid->fid_icb.lad_ext_loc))) == 0) { return (1); } /* LINTED */ if ((tag = (struct tag *)getblk(*in << l2b)) == NULL) { (void) fprintf(stdout, gettext("Could not read block %x\n"), *in); return (1); } if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, 0, 0, 1) != 0) { (void) fprintf(stdout, gettext("Not a file entry(inode)" " at %x\n"), *in); return (1); } if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, SWAP_32(tag->tag_loc), 1, 1) != 0) { (void) fprintf(stdout, gettext("CRC failed\n")); return (1); } return (0); } } return (err); } struct recu_dir { struct recu_dir *next; uint32_t inode; char *nm; }; void list(char *nm, uint32_t in, uint32_t fl) { uint8_t buf[1024]; uint64_t off; struct file_id *fid; struct recu_dir *rd, *erd, *temp; uint32_t iloc; rd = erd = temp = NULL; if (verify_inode(in << l2b, 4) == 0) { (void) fprintf(stdout, gettext("Inode is not a directory\n")); return; } if (fl & 2) { (void) printf("\n"); if (fl & 1) { (void) fprintf(stdout, gettext("i#: %x\t"), in); } (void) printf("%s\n", nm); } off = 0; /* LINTED */ fid = (struct file_id *)buf; while (get_fid(in, buf, off) == 0) { off += FID_LEN(fid); if (fid->fid_flags & FID_DELETED) { continue; } iloc = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn), SWAP_32(fid->fid_icb.lad_ext_loc)); if (fl & 1) { (void) fprintf(stdout, gettext("i#: %x\t"), iloc); } if (fid->fid_flags & FID_PARENT) { (void) fprintf(stdout, gettext("..\n")); } else { int32_t i; uint8_t *addr; addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; for (i = 0; i < fid->fid_idlen - 1; i++) (void) fprintf(stdout, "%c", addr[i]); (void) fprintf(stdout, "\n"); if ((fid->fid_flags & FID_DIR) && (fl & 2)) { temp = (struct recu_dir *) malloc(sizeof (struct recu_dir)); if (temp == NULL) { (void) fprintf(stdout, gettext("Could not allocate memory\n")); } else { temp->next = NULL; temp->inode = iloc; temp->nm = malloc(strlen(nm) + 1 + fid->fid_idlen + 1); if (temp->nm != NULL) { (void) strcpy(temp->nm, nm); (void) strcat(temp->nm, "/"); (void) strncat(temp->nm, (char *)addr, fid->fid_idlen); } if (rd == NULL) { erd = rd = temp; } else { erd->next = temp; erd = temp; } } } } } while (rd != NULL) { if (rd->nm != NULL) { list(rd->nm, rd->inode, fl); } else { list(".", rd->inode, fl); } temp = rd; rd = rd->next; if (temp->nm) { free(temp->nm); } free(temp); } } void fill_pattern(uint32_t addr, uint32_t count, char *pattern) { uint32_t beg, end, soff, lcount; int32_t len = strlen(pattern); caddr_t buf, p; if (openflg == O_RDONLY) { (void) fprintf(stdout, gettext("Not run with -w flag\n")); return; } if (count == 0) { count = 1; } beg = addr; end = addr + count * len; soff = beg & (~bmask); lcount = ((end + bmask) & (~bmask)) - soff; inval_bufs(); buf = malloc(lcount); if (llseek(fd, soff, SEEK_SET) != soff) { (void) fprintf(stdout, gettext("Seek failed fd %x off %llx errno %x\n"), fd, soff, errno); goto end; } if (read(fd, buf, lcount) != lcount) { (void) fprintf(stdout, gettext("Read failed fd %x off %llx errno %x\n"), fd, soff, errno); goto end; } p = buf + (addr & bmask); while (count--) { (void) strncpy(p, pattern, len); p += len; } if (write(fd, buf, lcount) != lcount) { (void) fprintf(stdout, gettext("Write failed fd %x off %llx errno %x\n"), fd, soff, errno); goto end; } end: free(buf); } void dump_disk(uint32_t addr, uint32_t count, char *format) { uint32_t beg, end, soff, lcount; int32_t len, prperline, n; uint8_t *buf, *p; uint16_t *p_16; uint32_t *p_32; if (strlen(format) != 1) { (void) fprintf(stdout, gettext("Invalid command\n")); return; } if (count == 0) { count = 1; } switch (*format) { case 'b' : /* FALLTHROUGH */ case 'c' : /* FALLTHROUGH */ case 'd' : /* FALLTHROUGH */ case 'o' : len = 1; prperline = 16; break; case 'x' : len = 2; prperline = 8; break; case 'D' : /* FALLTHROUGH */ case 'O' : /* FALLTHROUGH */ case 'X' : len = 4; prperline = 4; break; default : (void) fprintf(stdout, gettext("Invalid format\n")); return; } beg = addr; end = addr + count * len; soff = beg & (~bmask); lcount = ((end + bmask) & (~bmask)) - soff; inval_bufs(); buf = malloc(lcount); if (llseek(fd, soff, SEEK_SET) != soff) { (void) fprintf(stdout, gettext("Seek failed fd %x off %llx errno %x\n"), fd, soff, errno); goto end; } if (read(fd, buf, lcount) != lcount) { (void) fprintf(stdout, gettext("Read failed fd %x off %llx errno %x\n"), fd, soff, errno); goto end; } p = buf + (addr & bmask); /* LINTED */ p_16 = (uint16_t *)p; /* LINTED */ p_32 = (uint32_t *)p; n = 0; while (n < count) { switch (*format) { case 'b' : (void) fprintf(stdout, "%4x ", *((uint8_t *)p)); break; case 'c' : (void) fprintf(stdout, "%4c ", *((uint8_t *)p)); break; case 'd' : (void) fprintf(stdout, "%4d ", *((uint8_t *)p)); break; case 'o' : (void) fprintf(stdout, "%4o ", *((uint8_t *)p)); break; case 'x' : (void) fprintf(stdout, "%8x ", *p_16); break; case 'D' : (void) fprintf(stdout, "%16d ", *p_32); break; case 'O' : (void) fprintf(stdout, "%16o ", *p_32); break; case 'X' : (void) fprintf(stdout, "%16x ", *p_32); break; } p += len; n++; if ((n % prperline) == 0) { (void) fprintf(stdout, "\n"); } } if (n % prperline) { (void) fprintf(stdout, "\n"); } end: free(buf); } void find_it(char *dir, char *name, uint32_t in, uint32_t fl) { uint8_t buf[1024], *addr; uint64_t off; struct file_id *fid; uint32_t iloc, d_in; uint8_t d_fl; struct recu_dir *rd, *erd, *temp; rd = erd = temp = NULL; if (inode_from_path(dir, &d_in, &d_fl) != 0) { (void) fprintf(stdout, gettext("Could not find directory %s"), dir); return; } if ((d_fl & FID_DIR) == 0) { (void) fprintf(stdout, gettext("Path %s is not a directory\n"), dir); return; } if (verify_inode(d_in << l2b, 4) == 0) { (void) fprintf(stdout, gettext("Inode is not a directory\n")); return; } off = 0; /* LINTED */ fid = (struct file_id *)buf; while (get_fid(d_in, buf, off) == 0) { off += FID_LEN(fid); if ((fid->fid_flags & FID_DELETED) || (fid->fid_flags & FID_PARENT)) { continue; } iloc = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn), SWAP_32(fid->fid_icb.lad_ext_loc)); addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; if (((fl & 4) && (in == iloc)) || ((fl & 2) && (strcmp(name, (char *)addr) == 0))) { (void) printf("%s %x %s\n", dir, iloc, addr); } if (fid->fid_flags & FID_DIR) { temp = (struct recu_dir *) malloc(sizeof (struct recu_dir)); if (temp == NULL) { (void) fprintf(stdout, gettext("Could not allocate memory\n")); } else { temp->next = NULL; temp->inode = iloc; temp->nm = malloc(strlen(dir) + 1 + fid->fid_idlen + 1); if (temp->nm != NULL) { (void) strcpy(temp->nm, dir); (void) strcat(temp->nm, "/"); (void) strncat(temp->nm, (char *)addr, fid->fid_idlen); } else { (void) fprintf(stdout, gettext( "Could not allocate memory\n")); } if (rd == NULL) { erd = rd = temp; } else { erd->next = temp; erd = temp; } } } } while (rd != NULL) { if (rd->nm != NULL) { find_it(rd->nm, name, in, fl); } temp = rd; rd = rd->next; if (temp->nm) { free(temp->nm); } free(temp); } } %{ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include "y.tab.h" extern int base; int cmd_no = 1; %} %e 2000 WS [ \t] %% \n { cmd_no++; return NL; } \. { return DOT; } ;{WS}*:{WS}*base{WS}* { return BASE; } ^{WS}*:{WS}*base{WS}* { return BASE; } {WS}*:{WS}*block{WS}* { return BLOCK; } ;{WS}*:{WS}*cd { return CD; } ^{WS}*:{WS}*cd { return CD; } :{WS}*directory{WS}* { return DIRECTORY; } :{WS}*file{WS}* { return TFILE; } ;{WS}*:{WS}*find{WS}* { return FIND; } ^{WS}*:{WS}*find{WS}* { return FIND; } {WS}*:{WS}*fill{WS}* { return FILL; } :{WS}*inode{WS}* { return INODE; } ;{WS}*:{WS}*ls { return LS; } ^{WS}*:{WS}*ls { return LS; } ;{WS}*:{WS}*override{WS}* { return OVERRIDE; } ^{WS}*:{WS}*override{WS}* { return OVERRIDE; } ;{WS}*:{WS}*prompt{WS}* { return PROMPT; } ^{WS}*:{WS}*prompt{WS}* { return PROMPT; } ;{WS}*:{WS}*pwd{WS}* { return PWD; } ^{WS}*:{WS}*pwd{WS}* { return PWD; } ;{WS}*:{WS}*quit{WS}* { return QUIT; } ^{WS}*:{WS}*quit{WS}* { return QUIT; } :{WS}*tag{WS}* { return TAG; } ;{WS}*:{WS}*!{WS}* { return BANG; } ^{WS}*:{WS}*!{WS}* { return BANG; } :{WS}*avd { return AVD; } :{WS}*mvds { return MVDS; } :{WS}*rvds { return RVDS; } :{WS}*ints { return INTS; } :{WS}*fsds { return FSDS; } :{WS}*root { return ROOT; } :{WS}*attz { return ATTZ; } :{WS}*atye { return ATYE; } :{WS}*atmo { return ATMO; } :{WS}*atda { return ATDA; } :{WS}*atho { return ATHO; } :{WS}*atmi { return ATMI; } :{WS}*atse { return ATSE; } :{WS}*atce { return ATCE; } :{WS}*athu { return ATHU; } :{WS}*atmic { return ATMIC; } :{WS}*cttz { return CTTZ; } :{WS}*ctye { return CTYE; } :{WS}*ctmo { return CTMO; } :{WS}*ctda { return CTDA; } :{WS}*ctho { return CTHO; } :{WS}*ctmi { return CTMI; } :{WS}*ccte { return CTSE; } :{WS}*ctce { return CTCE; } :{WS}*cthu { return CTHU; } :{WS}*ctmic { return CTMIC; } :{WS}*mttz { return MTTZ; } :{WS}*mtye { return MTYE; } :{WS}*mtmo { return MTMO; } :{WS}*mtda { return MTDA; } :{WS}*mtho { return MTHO; } :{WS}*mtmi { return MTMI; } :{WS}*mtse { return MTSE; } :{WS}*mtce { return MTCE; } :{WS}*mthu { return MTHU; } :{WS}*mtmic { return MTMIC; } :{WS}*gid { return GID; } :{WS}*ln { return LN; } :{WS}*md { return MD; } :{WS}*maj { return MAJ; } :{WS}*min { return MIO; } :{WS}*nm { return NM; } :{WS}*sz { return SZ; } :{WS}*uid { return UID; } :{WS}*uniq { return UNIQ; } [-0-9a-zA-Z._]+ { yylval.strval = yytext; return WORD; } . { return yytext[0]; } %% void yyerror() { fprintf(stderr, gettext("Syntax error line : %d token : %s \n"), cmd_no, yytext); } /* :{WS}*fsds { return FSDS; } :{WS}*root { return ROOT; } */ %{ /* * 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. */ #include #include #include #include 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 WORD %type 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; } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (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) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # # # MAPFILE HEADER START # # WARNING: STOP NOW. DO NOT MODIFY THIS FILE. # Object versioning must comply with the rules detailed in # # usr/src/lib/README.mapfiles # # You should not be making modifications here until you've read the most current # copy of that file. If you need help, contact a gatekeeper for guidance. # # MAPFILE HEADER END # $mapfile_version 2 # fsdb uses the -e option of lex, which generates additional lex interfaces # that are not defined in the generic $(MAPFILE.LEX). These additional lex # interfaces are exported here. SYMBOL_SCOPE { global: yywinput; yywleng; yywtext; yywunput; };