fsdb.c 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 <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <inttypes.h>
#include <libgen.h>
#include <locale.h>
#include <sys/param.h>
#include <sys/signal.h>
#include <sys/file.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/vnode.h>
#include <sys/mntent.h>
#include <sys/wait.h>
#include <sys/vtoc.h>
#include <sys/dkio.h>
#include <sys/fs/udf_volume.h>
#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();
extern void print_tag(struct tag *);
extern void print_pvd(struct pri_vol_desc *);
extern void print_avd(struct anch_vol_desc_ptr *);
extern void print_vdp(struct vol_desc_ptr *);
extern void print_iuvd(struct iuvd_desc *);
extern void print_part(struct part_desc *);
extern void print_lvd(struct log_vol_desc *);
extern void print_usd(struct unall_spc_desc *);
extern void print_lvid(struct log_vol_int_desc *);
extern void print_part(struct part_desc *);
extern void print_fsd(struct file_set_desc *);
extern void print_aed(struct alloc_ext_desc *);
extern void print_ie(struct indirect_entry *);
extern void print_td(struct term_desc *);
extern void print_fe(struct file_entry *);
extern void ud_make_tag(struct tag *, uint16_t, uint32_t, uint16_t);
extern void print_fid(struct file_id *);
extern int32_t ud_open_dev(char *, uint32_t);
extern int32_t ud_verify_tag(struct tag *, uint16_t,
uint32_t, int32_t, int32_t);
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
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 ((fd = ud_open_dev(argv[optind], openflg)) < 0) {
perror("open");
exit(1);
}
if ((ret = ud_fill_udfs_info(fd)) != 0) {
return (ret);
}
if ((udfs.flags & VALID_UDFS) == 0) {
return (1);
}
bsize = udfs.lbsize;
bmask = bsize - 1;
l2d = 0;
while ((bsize >> l2d) > DEV_BSIZE) {
l2d++;
}
l2b = l2d + 9;
ricb_prn = udfs.ricb_prn;
ricb_loc = udfs.ricb_loc;
ricb_len = udfs.ricb_len;
value = i_number = ud_xlate_to_daddr(ricb_prn, ricb_loc);
init_buffers();
run_fsdb();
(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 * udfs.lbsize);
bhdr.fwd = bhdr.back = &bhdr;
for (i = 0; i < NBUF; i++) {
bp = &lbuf[i];
bp->blkaddr = addr + i * 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, udfs.lbsize) != 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, udfs.lbsize) == 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 != NULL) {
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(
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 = udfs.mvds_loc;
end = i +
(udfs.mvds_len >> l2b);
} else if (id == RVDS) {
i = udfs.rvds_loc;
end = i +
(udfs.rvds_len >> l2b);
} else {
i = udfs.lvid_loc;
end = i +
(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 = udfs.fsds_prn;
i = udfs.fsds_loc;
end = i +
(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(
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((struct pri_vol_desc *)tag);
break;
case UD_ANCH_VOL_DESC :
print_avd((struct anch_vol_desc_ptr *)tag);
break;
case UD_VOL_DESC_PTR :
print_vdp((struct vol_desc_ptr *)tag);
break;
case UD_IMPL_USE_DESC :
print_iuvd((struct iuvd_desc *)tag);
break;
case UD_PART_DESC :
print_part((struct part_desc *)tag);
break;
case UD_LOG_VOL_DESC :
print_lvd((struct log_vol_desc *)tag);
break;
case UD_UNALL_SPA_DESC :
print_usd((struct unall_spc_desc *)tag);
break;
case UD_TERM_DESC :
(void) fprintf(stdout, "TERM DESC\n");
print_tag(tag);
break;
case UD_LOG_VOL_INT :
/* LINTED */
print_lvid((struct log_vol_int_desc *)tag);
break;
case UD_FILE_SET_DESC :
print_fsd((struct file_set_desc *)tag);
break;
case UD_FILE_ID_DESC :
print_fid((struct file_id *)tag);
break;
case UD_ALLOC_EXT_DESC :
print_aed((struct alloc_ext_desc *)tag);
break;
case UD_INDIRECT_ENT :
print_ie((struct indirect_entry *)tag);
break;
case UD_TERMINAL_ENT :
print_td((struct term_desc *)tag);
break;
case UD_FILE_ENTRY :
/* LINTED */
print_fe((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(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(&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(&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(&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(&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(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(tag, UD_FILE_ENTRY,
SWAP_32(tag->tag_loc), 1, 1) != 0) {
(void) fprintf(stdout,
gettext("CRC failed\n"));
} else {
/* LINTED */
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(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;
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++) {
if (desc_type == ICB_FLAG_SHORT_AD) {
prn = 0;
bno = SWAP_32(sad->sad_ext_loc);
len = SWAP_32(sad->sad_ext_len);
} else if (desc_type == 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);
}
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(
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 = 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(&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(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(
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(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(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(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(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);
}
}