xref: /titanic_52/usr/src/cmd/fs.d/udfs/fsdb/fsdb.c (revision d58fda4376e4bf67072ce2e69f6f47036f9dbb68)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <fcntl.h>
35 #include <signal.h>
36 #include <setjmp.h>
37 #include <errno.h>
38 #include <inttypes.h>
39 #include <libgen.h>
40 #include <locale.h>
41 
42 #include <sys/param.h>
43 #include <sys/signal.h>
44 #include <sys/file.h>
45 #include <sys/sysmacros.h>
46 #include <sys/types.h>
47 #include <sys/vnode.h>
48 #include <sys/mntent.h>
49 #include <sys/wait.h>
50 #include <sys/vtoc.h>
51 #include <sys/dkio.h>
52 
53 #include <sys/fs/udf_volume.h>
54 #include "ud_lib.h"
55 #include "y.tab.h"
56 
57 typedef unsigned short unicode_t;
58 #define	MAXNAMLEN	0x200
59 
60 extern uint32_t i_number;
61 
62 extern int32_t run_fsdb();
63 extern void print_tag(struct tag *);
64 extern void print_pvd(struct pri_vol_desc *);
65 extern void print_avd(struct anch_vol_desc_ptr *);
66 extern void print_vdp(struct vol_desc_ptr *);
67 extern void print_iuvd(struct iuvd_desc *);
68 extern void print_part(struct part_desc *);
69 extern void print_lvd(struct log_vol_desc *);
70 extern void print_usd(struct unall_spc_desc *);
71 extern void print_lvid(struct log_vol_int_desc *);
72 extern void print_part(struct part_desc *);
73 extern void print_fsd(struct file_set_desc *);
74 extern void print_aed(struct alloc_ext_desc *);
75 extern void print_ie(struct indirect_entry *);
76 extern void print_td(struct term_desc *);
77 extern void print_fe(struct file_entry *);
78 extern void ud_make_tag(struct tag *, uint16_t, uint32_t, uint16_t);
79 extern void print_fid(struct file_id *);
80 
81 
82 extern int32_t ud_open_dev(char *, uint32_t);
83 extern int32_t ud_verify_tag(struct tag *, uint16_t,
84 		uint32_t, int32_t, int32_t);
85 
86 void usage();
87 void init_buffers();
88 char *getblk(u_offset_t);
89 int32_t parse_udfs(uint32_t);
90 int32_t parse_vds(uint32_t, uint32_t);
91 int32_t parse_part(struct part_desc *);
92 int32_t parse_lvd(struct log_vol_desc *);
93 int32_t parse_fsds();
94 int32_t get_vat_loc();
95 int32_t get_fid(uint32_t, uint8_t *, uint64_t);
96 
97 
98 char *progname;
99 char prompt[256] = "fsdb>";
100 
101 #define	ARG_OVERRIDE	0
102 #define	ARG_NEW_PROMPT	1
103 #define	ARG_WR_ENABLED	2
104 #define	ARG_USAGE	3
105 
106 char *subopt_v[] = {
107 	"o",
108 	"p",
109 	"w",
110 	"?",
111 	NULL
112 };
113 int32_t override = 0;
114 int32_t openflg = O_RDONLY;
115 
116 #define	MAX_PARTS	10
117 
118 /*
119  * udp_flags
120  */
121 #define	UDP_BITMAPS	0x00
122 #define	UDP_SPACETBLS	0x01
123 
124 
125 int32_t fd, nparts, nmaps;
126 int32_t bmask, l2d, l2b;
127 
128 
129 uint16_t ricb_prn;
130 uint32_t ricb_loc, ricb_len;
131 extern int value;
132 
133 
134 int32_t
135 main(int argc, char *argv[])
136 {
137 	int opt, ret;
138 	uint32_t bsize;
139 	char *subopts, *optval;
140 
141 #if !defined(TEXT_DOMAIN)
142 #define	TEXT_DOMAIN "SYS_TEST"
143 #endif
144 	(void) textdomain(TEXT_DOMAIN);
145 
146 	progname = argv[0];
147 
148 	while ((opt = getopt(argc, argv, "o:")) != EOF) {
149 		switch (opt) {
150 		case 'o' :
151 			subopts = optarg;
152 			while (*subopts != '\0') {
153 				switch (getsubopt(&subopts,
154 					subopt_v, &optval)) {
155 				case ARG_OVERRIDE :
156 					override = 1;
157 					(void) fprintf(stdout,
158 					gettext("error checking off\n"));
159 					break;
160 				case ARG_NEW_PROMPT :
161 					if (optval == NULL) {
162 						usage();
163 					}
164 					if (strlen(optval) > 255) {
165 						(void) fprintf(stdout,
166 						gettext("prompt should be less"
167 						"than 255 bytes\n"));
168 						exit(1);
169 					}
170 					(void) strcpy(prompt, optval);
171 					break;
172 				case ARG_WR_ENABLED :
173 					openflg = O_RDWR;
174 					break;
175 				case ARG_USAGE :
176 				default :
177 					usage();
178 				}
179 			}
180 			break;
181 		default :
182 			usage();
183 		}
184 	}
185 
186 	if ((argc - optind) != 1) {	/* Should just have "special" left */
187 		usage();
188 	}
189 
190 
191 	if ((fd = ud_open_dev(argv[optind], openflg)) < 0) {
192 		perror("open");
193 		exit(1);
194 	}
195 
196 	if ((ret = ud_fill_udfs_info(fd)) != 0) {
197 		return (ret);
198 	}
199 
200 	if ((udfs.flags & VALID_UDFS) == 0) {
201 		return (1);
202 	}
203 
204 	bsize = udfs.lbsize;
205 	bmask = bsize - 1;
206 	l2d = 0;
207 	while ((bsize >> l2d) > DEV_BSIZE) {
208 		l2d++;
209 	}
210 	l2b = l2d + 9;
211 
212 	ricb_prn = udfs.ricb_prn;
213 	ricb_loc = udfs.ricb_loc;
214 	ricb_len = udfs.ricb_len;
215 
216 	value = i_number = ud_xlate_to_daddr(ricb_prn, ricb_loc);
217 
218 	init_buffers();
219 
220 	run_fsdb();
221 
222 	(void) close(fd);
223 
224 	return (0);
225 }
226 
227 /*
228  * usage - print usage and exit
229  */
230 void
231 usage()
232 {
233 	(void) fprintf(stdout,
234 		gettext("usage:   %s [options] special\n"), progname);
235 	(void) fprintf(stdout,
236 		gettext("options:\n"));
237 	(void) fprintf(stdout,
238 		gettext("\t-o\tSpecify udfs filesystem sepcific options\n"));
239 	(void) fprintf(stdout,
240 		gettext("\t\tAvailable suboptions are:\n"));
241 	(void) fprintf(stdout,
242 		gettext("\t\t?\tdisplay usage\n"));
243 	(void) fprintf(stdout,
244 		gettext("\t\to\toverride some error conditions\n"));
245 	(void) fprintf(stdout,
246 		gettext("\t\tp\t\"string\" set prompt to string\n"));
247 	(void) fprintf(stdout,
248 		gettext("\t\tw\topen for write\n"));
249 	exit(1);
250 }
251 
252 #define	NBUF	10
253 static struct lbuf {
254 	struct lbuf	*fwd;
255 	struct lbuf	*back;
256 	int32_t		valid;
257 	char		*blkaddr;
258 	u_offset_t	blkno;
259 } lbuf[NBUF], bhdr;
260 
261 #define	INSERT(bp)	\
262 	{ \
263 		bp->back = &bhdr; \
264 		bp->fwd = bhdr.fwd; \
265 		bhdr.fwd->back = bp; \
266 		bhdr.fwd = bp; \
267 	}
268 
269 void
270 init_buffers()
271 {
272 	int32_t i;
273 	char *addr;
274 	struct lbuf *bp;
275 
276 	addr = malloc(NBUF * udfs.lbsize);
277 	bhdr.fwd = bhdr.back = &bhdr;
278 	for (i = 0; i < NBUF; i++) {
279 		bp = &lbuf[i];
280 		bp->blkaddr = addr + i * udfs.lbsize;
281 		bp->valid = 0;
282 		INSERT(bp);
283 	}
284 }
285 
286 char *
287 getblk(u_offset_t address)
288 {
289 	u_offset_t off, block;
290 	struct lbuf *bp;
291 
292 	off = address & ~bmask;
293 	block = address >> l2b;
294 	for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) {
295 		if (bp->valid && bp->blkno == block) {
296 			goto found;
297 		}
298 	}
299 	bp = bhdr.back;
300 	bp->blkno = block;
301 	bp->valid = 0;
302 	errno = 0;
303 	if (llseek(fd, off, SEEK_SET) != off) {
304 		(void) fprintf(stdout,
305 			gettext("Seek failed fd %x off %llx errno %x\n"),
306 			fd, off, errno);
307 		return (NULL);
308 	}
309 	errno = 0;
310 	if (read(fd, bp->blkaddr, udfs.lbsize) != udfs.lbsize) {
311 		(void) fprintf(stdout,
312 			gettext("Read failed fd %x off %llx errno %x\n"),
313 			fd, off, errno);
314 		return (NULL);
315 	}
316 	bp->valid = 1;
317 found:
318 	bp->back->fwd = bp->fwd;
319 	bp->fwd->back = bp->back;
320 	INSERT(bp);
321 	return (bp->blkaddr);
322 }
323 
324 
325 int32_t
326 putblk(caddr_t address)
327 {
328 	u_offset_t off;
329 	struct lbuf *bp;
330 
331 	if (openflg == O_RDONLY) {
332 		(void) fprintf(stdout,
333 			gettext("Not run with -w flag\n"));
334 		return (1);
335 	}
336 
337 	for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) {
338 		if (bp->valid && bp->blkaddr == address) {
339 			goto found;
340 		}
341 	}
342 	(void) fprintf(stdout,
343 		gettext("Could not find the buffer\n"));
344 	return (1);
345 
346 found:
347 	off = bp->blkno << l2b;
348 	if (llseek(fd, off, SEEK_SET) == off) {
349 		if (write(fd, bp->blkaddr, udfs.lbsize) == udfs.lbsize) {
350 			return (0);
351 		}
352 		(void) fprintf(stdout,
353 			gettext("Write failed fd %x off %llx errno %x\n"),
354 			fd, off, errno);
355 	} else {
356 		(void) fprintf(stdout,
357 			gettext("Seek failed fd %x off %llx errno %x\n"),
358 			fd, off, errno);
359 	}
360 	return (1);
361 }
362 
363 void
364 inval_bufs()
365 {
366 	struct lbuf *bp;
367 
368 	for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) {
369 		bp->valid = 0;
370 	}
371 }
372 
373 /*
374  * If addr == NULL then use id to print the desc
375  * other wise use addr to self identify the type of desc
376  */
377 void
378 print_desc(uint32_t addr, int32_t id)
379 {
380 	struct tag *tag;
381 	caddr_t baddr;
382 
383 	/*
384 	 * Read the block at addr
385 	 * find out the type of tag
386 	 * and print the descriptor
387 	 */
388 	if (addr != NULL) {
389 		if ((baddr = getblk(addr & (~bmask))) == NULL) {
390 			(void) fprintf(stdout,
391 				gettext("Could not read block %x\n"),
392 				addr >> l2b);
393 		}
394 		/* LINTED */
395 		tag = (struct tag *)(baddr + (addr & bmask));
396 	} else {
397 		switch (id) {
398 			case AVD :
399 				/* LINTED */
400 				if ((tag = (struct tag *)getblk(
401 					udfs.avdp_loc << l2b)) == NULL) {
402 					(void) fprintf(stdout,
403 					gettext("Could not read AVDP\n"));
404 				}
405 				break;
406 			case MVDS :
407 			case RVDS :
408 			case INTS :
409 				{
410 					uint32_t i, end;
411 
412 					if (id == MVDS) {
413 						i = udfs.mvds_loc;
414 						end = i +
415 						(udfs.mvds_len >> l2b);
416 					} else if (id == RVDS) {
417 						i = udfs.rvds_loc;
418 						end = i +
419 						(udfs.rvds_len >> l2b);
420 					} else {
421 						i = udfs.lvid_loc;
422 						end = i +
423 						(udfs.lvid_len >> l2b);
424 					}
425 
426 					for (; i < end; i++) {
427 						print_desc(i << l2b, 0);
428 					}
429 				}
430 				return;
431 			case FSDS :
432 			case ROOT :
433 				{
434 					uint16_t prn;
435 					uint32_t i, end, block;
436 
437 					if (id == FSDS) {
438 						prn = udfs.fsds_prn;
439 						i = udfs.fsds_loc;
440 						end = i +
441 						(udfs.fsds_len >> l2b);
442 					} else {
443 						prn = ricb_prn;
444 						i = ricb_loc;
445 						end = i + (ricb_len >> l2b);
446 					}
447 
448 					for (; i < end; i++) {
449 						if ((block = ud_xlate_to_daddr(
450 							prn, i)) == 0) {
451 							(void) fprintf(stdout,
452 							gettext("Cannot xlate "
453 							"prn %x loc %x\n"),
454 							prn, i);
455 							continue;
456 						}
457 						print_desc(block << l2b, 0);
458 					}
459 				}
460 				/* FALLTHROUGH */
461 			default :
462 				return;
463 		}
464 	}
465 
466 	switch (SWAP_16(tag->tag_id)) {
467 		case UD_PRI_VOL_DESC :
468 			print_pvd((struct pri_vol_desc *)tag);
469 			break;
470 		case UD_ANCH_VOL_DESC :
471 			print_avd((struct anch_vol_desc_ptr *)tag);
472 			break;
473 		case UD_VOL_DESC_PTR :
474 			print_vdp((struct vol_desc_ptr *)tag);
475 			break;
476 		case UD_IMPL_USE_DESC :
477 			print_iuvd((struct iuvd_desc *)tag);
478 			break;
479 		case UD_PART_DESC :
480 			print_part((struct part_desc *)tag);
481 			break;
482 		case UD_LOG_VOL_DESC :
483 			print_lvd((struct log_vol_desc *)tag);
484 			break;
485 		case UD_UNALL_SPA_DESC :
486 			print_usd((struct unall_spc_desc *)tag);
487 			break;
488 		case UD_TERM_DESC :
489 			(void) fprintf(stdout, "TERM DESC\n");
490 			print_tag(tag);
491 			break;
492 		case UD_LOG_VOL_INT :
493 			/* LINTED */
494 			print_lvid((struct log_vol_int_desc *)tag);
495 			break;
496 		case UD_FILE_SET_DESC :
497 			print_fsd((struct file_set_desc *)tag);
498 			break;
499 		case UD_FILE_ID_DESC :
500 			print_fid((struct file_id *)tag);
501 			break;
502 		case UD_ALLOC_EXT_DESC :
503 			print_aed((struct alloc_ext_desc *)tag);
504 			break;
505 		case UD_INDIRECT_ENT :
506 			print_ie((struct indirect_entry *)tag);
507 			break;
508 		case UD_TERMINAL_ENT :
509 			print_td((struct term_desc *)tag);
510 			break;
511 		case UD_FILE_ENTRY :
512 			/* LINTED */
513 			print_fe((struct file_entry *)tag);
514 			break;
515 		case UD_EXT_ATTR_HDR :
516 		case UD_UNALL_SPA_ENT :
517 		case UD_SPA_BMAP_DESC :
518 		case UD_PART_INT_DESC :
519 		case UD_EXT_FILE_ENT :
520 			break;
521 		default :
522 			(void) fprintf(stdout,
523 				gettext("unknown descriptor\n"));
524 			print_tag(tag);
525 			break;
526 	}
527 }
528 
529 void
530 set_file(int32_t id, uint32_t iloc, uint64_t value)
531 {
532 	uint8_t i8;
533 	uint16_t i16;
534 	uint32_t i32, block, ea_len, ea_off;
535 	uint64_t i64;
536 	struct file_entry *fe;
537 	struct dev_spec_ear *ds;
538 	struct attr_hdr *ah;
539 	struct ext_attr_hdr *eah;
540 
541 	/* LINTED */
542 	if ((fe = (struct file_entry *)getblk(iloc)) == NULL) {
543 		return;
544 	}
545 	if (ud_verify_tag(&fe->fe_tag, UD_FILE_ENTRY,
546 			SWAP_32(fe->fe_tag.tag_loc), 1, 1) != 0) {
547 		return;
548 	}
549 	i8 = (uint8_t)value;
550 	i16 = SWAP_16(((uint16_t)value));
551 	i32 = SWAP_32(((uint32_t)value));
552 	i64 = SWAP_64(value);
553 	switch (id) {
554 		case ATTZ :
555 			fe->fe_acc_time.ts_tzone = i16;
556 			break;
557 		case ATYE  :
558 			fe->fe_acc_time.ts_year = i16;
559 			break;
560 		case ATMO  :
561 			fe->fe_acc_time.ts_month = i8;
562 			break;
563 		case ATDA  :
564 			fe->fe_acc_time.ts_day = i8;
565 			break;
566 		case ATHO  :
567 			fe->fe_acc_time.ts_hour = i8;
568 			break;
569 		case ATMI  :
570 			fe->fe_acc_time.ts_min = i8;
571 			break;
572 		case ATSE  :
573 			fe->fe_acc_time.ts_sec = i8;
574 			break;
575 		case ATCE  :
576 			fe->fe_acc_time.ts_csec = i8;
577 			break;
578 		case ATHU  :
579 			fe->fe_acc_time.ts_husec = i8;
580 			break;
581 		case ATMIC :
582 			fe->fe_acc_time.ts_usec = i8;
583 			break;
584 		case CTTZ  :
585 			fe->fe_attr_time.ts_tzone = i16;
586 			break;
587 		case CTYE  :
588 			fe->fe_attr_time.ts_year = i16;
589 			break;
590 		case CTMO  :
591 			fe->fe_attr_time.ts_month = i8;
592 			break;
593 		case CTDA  :
594 			fe->fe_attr_time.ts_day = i8;
595 			break;
596 		case CTHO  :
597 			fe->fe_attr_time.ts_hour = i8;
598 			break;
599 		case CTMI  :
600 			fe->fe_attr_time.ts_min = i8;
601 			break;
602 		case CTSE  :
603 			fe->fe_attr_time.ts_sec = i8;
604 			break;
605 		case CTCE  :
606 			fe->fe_attr_time.ts_csec = i8;
607 			break;
608 		case CTHU  :
609 			fe->fe_attr_time.ts_husec = i8;
610 			break;
611 		case CTMIC :
612 			fe->fe_attr_time.ts_usec = i8;
613 			break;
614 		case MTTZ  :
615 			fe->fe_mod_time.ts_tzone = i16;
616 			break;
617 		case MTYE  :
618 			fe->fe_mod_time.ts_year = i16;
619 			break;
620 		case MTMO  :
621 			fe->fe_mod_time.ts_month = i8;
622 			break;
623 		case MTDA  :
624 			fe->fe_mod_time.ts_day = i8;
625 			break;
626 		case MTHO  :
627 			fe->fe_mod_time.ts_hour = i8;
628 			break;
629 		case MTMI  :
630 			fe->fe_mod_time.ts_min = i8;
631 			break;
632 		case MTSE  :
633 			fe->fe_mod_time.ts_sec = i8;
634 			break;
635 		case MTCE  :
636 			fe->fe_mod_time.ts_csec = i8;
637 			break;
638 		case MTHU  :
639 			fe->fe_mod_time.ts_husec = i8;
640 			break;
641 		case MTMIC :
642 			fe->fe_mod_time.ts_usec = i8;
643 			break;
644 		case GID  :
645 			fe->fe_gid = i32;
646 			break;
647 		case LN  :
648 			fe->fe_lcount = i16;
649 			break;
650 		case MD  :
651 			fe->fe_perms = i32;
652 			break;
653 		case MAJ  :
654 		case MIO  :
655 			if ((fe->fe_icb_tag.itag_ftype != VBLK) &&
656 				(fe->fe_icb_tag.itag_ftype != VCHR)) {
657 				(void) fprintf(stdout,
658 					gettext("Not a device\n"));
659 				break;
660 			}
661 			/* LINTED */
662 			eah = (struct ext_attr_hdr *)fe->fe_spec;
663 			ea_off = SWAP_32(eah->eah_ial);
664 			ea_len = SWAP_32(fe->fe_len_ear);
665 			block = SWAP_32(eah->eah_tag.tag_loc);
666 			if (ea_len && (ud_verify_tag(&eah->eah_tag,
667 				UD_EXT_ATTR_HDR, block, 1, 1) == 0)) {
668 				while (ea_off < ea_len) {
669 					/* LINTED */
670 					ah = (struct attr_hdr *)
671 						&fe->fe_spec[ea_off];
672 					if ((ah->ahdr_atype == SWAP_32(12)) &&
673 						(ah->ahdr_astype == 1)) {
674 
675 						ds = (struct dev_spec_ear *)ah;
676 						if (id == MAJ) {
677 							ds->ds_major_id = i32;
678 						} else {
679 							ds->ds_minor_id = i32;
680 						}
681 						ud_make_tag(&eah->eah_tag,
682 							UD_EXT_ATTR_HDR, block,
683 						eah->eah_tag.tag_crc_len);
684 						break;
685 					}
686 				}
687 			}
688 			(void) fprintf(stdout,
689 			gettext("does not have a Device Specification EA\n"));
690 			break;
691 		case NM  :
692 			break;
693 		case SZ  :
694 			fe->fe_info_len = i64;
695 			break;
696 		case UID  :
697 			fe->fe_uid = i32;
698 			break;
699 		case UNIQ :
700 			fe->fe_uniq_id = i32;
701 			break;
702 		default :
703 			(void) fprintf(stdout,
704 				gettext("Unknown set\n"));
705 	}
706 	ud_make_tag(&fe->fe_tag, UD_FILE_ENTRY,
707 		SWAP_32(fe->fe_tag.tag_loc), fe->fe_tag.tag_crc_len);
708 	(void) putblk((caddr_t)fe);
709 }
710 
711 caddr_t
712 verify_inode(uint32_t addr, uint32_t type)
713 {
714 	struct file_entry *fe;
715 	struct tag *tag;
716 
717 	/* LINTED */
718 	if ((tag = (struct tag *)getblk(addr & (~bmask))) == NULL) {
719 		(void) fprintf(stdout,
720 			gettext("Could not read block %x\n"),
721 			addr >> l2b);
722 	} else {
723 		if (ud_verify_tag(tag, UD_FILE_ENTRY, addr >> l2b, 0, 1) != 0) {
724 			(void) fprintf(stdout,
725 				gettext("Not a file entry(inode) at %x\n"),
726 				addr >> l2b);
727 		} else {
728 			if (ud_verify_tag(tag, UD_FILE_ENTRY,
729 				SWAP_32(tag->tag_loc), 1, 1) != 0) {
730 				(void) fprintf(stdout,
731 					gettext("CRC failed\n"));
732 			} else {
733 				/* LINTED */
734 				fe = (struct file_entry *)tag;
735 				if ((type == 0) ||
736 					(type == fe->fe_icb_tag.itag_ftype)) {
737 					return ((caddr_t)tag);
738 				}
739 			}
740 		}
741 	}
742 	return (0);
743 }
744 
745 void
746 print_inode(uint32_t addr)
747 {
748 	if (verify_inode(addr, 0) != NULL) {
749 		print_desc(addr, 0);
750 	}
751 }
752 
753 int32_t
754 verify_dent(uint32_t i_addr, uint32_t nent)
755 {
756 	uint32_t ent = 0;
757 	uint64_t off = 0;
758 	uint8_t buf[1024];
759 	struct file_id *fid;
760 
761 	/* LINTED */
762 	fid = (struct file_id *)buf;
763 
764 	if (verify_inode(i_addr, 4) == 0) {
765 		(void) fprintf(stdout,
766 			gettext("Inode is not a directory\n"));
767 		return (1);
768 	}
769 
770 	while (get_fid(i_addr >> l2b, buf, off) == 0) {
771 		off += FID_LEN(fid);
772 		if (ent == nent) {
773 			return (0);
774 		}
775 		ent++;
776 	}
777 	(void) fprintf(stdout,
778 		gettext("Reached EOF\n"));
779 	return (1);
780 }
781 
782 void
783 print_dent(uint32_t i_addr, uint32_t nent)
784 {
785 	uint32_t ent = 0;
786 	uint64_t off = 0;
787 	uint8_t buf[1024];
788 	struct file_id *fid;
789 
790 	/* LINTED */
791 	fid = (struct file_id *)buf;
792 
793 	if (verify_dent(i_addr, nent) == 0) {
794 		while (get_fid(i_addr >> l2b, buf, off) == 0) {
795 			off += FID_LEN(fid);
796 			if (ent == nent) {
797 				print_fid(fid);
798 				return;
799 			}
800 			ent++;
801 		}
802 	}
803 }
804 
805 uint32_t in;
806 uint32_t de_count, ie_count;
807 struct ext {
808 	uint16_t prn;
809 	uint16_t flags;
810 	uint32_t blkno;
811 	uint32_t len;
812 } *de, *ie;
813 
814 int32_t
815 get_blkno(uint32_t inode, uint32_t *blkno, uint64_t off)
816 {
817 	struct file_entry *fe;
818 	int32_t i, d, nent;
819 	uint16_t prn, flags, elen;
820 	uint32_t desc_type, bno, len;
821 	struct short_ad *sad;
822 	struct long_ad *lad;
823 	uint64_t b_off, e_off;
824 
825 	if (inode != in) {
826 		/* LINTED */
827 		if ((fe = (struct file_entry *)
828 				getblk(inode << l2b)) == NULL) {
829 			(void) fprintf(stdout,
830 				gettext("Could not read block %x\n"),
831 				off & (~bmask));
832 			return (1);
833 		}
834 		desc_type = SWAP_16(fe->fe_icb_tag.itag_flags) & 0x7;
835 		if (desc_type == ICB_FLAG_SHORT_AD) {
836 			elen = sizeof (struct short_ad);
837 			/* LINTED */
838 			sad = (struct short_ad *)
839 				(fe->fe_spec + SWAP_32(fe->fe_len_ear));
840 		} else if (desc_type == ICB_FLAG_LONG_AD) {
841 			elen = sizeof (struct long_ad);
842 			/* LINTED */
843 			lad = (struct long_ad *)
844 				(fe->fe_spec + SWAP_32(fe->fe_len_ear));
845 		} else if (desc_type == ICB_FLAG_ONE_AD) {
846 			*blkno = inode;
847 			return (0);
848 		} else {
849 			/* This cannot happen return */
850 			return (EINVAL);
851 		}
852 
853 		nent = SWAP_32(fe->fe_len_adesc) / elen;
854 		de = malloc(nent * sizeof (struct ext));
855 		if (de == NULL) {
856 			(void) fprintf(stdout,
857 				gettext("could not allocate memeory\n"));
858 			return (1);
859 		}
860 		in = inode;
861 		de_count = nent;
862 		for (d = 0, i = 0; i < nent; i++) {
863 			if (desc_type == ICB_FLAG_SHORT_AD) {
864 				prn = 0;
865 				bno = SWAP_32(sad->sad_ext_loc);
866 				len = SWAP_32(sad->sad_ext_len);
867 			} else if (desc_type == ICB_FLAG_LONG_AD) {
868 				prn = SWAP_16(lad->lad_ext_prn);
869 				bno = SWAP_32(lad->lad_ext_loc);
870 				len = SWAP_32(lad->lad_ext_len);
871 			}
872 			flags = len >> 30;
873 			if (flags == 0x3) {
874 				(void) fprintf(stdout,
875 					gettext("Handle IE\n"));
876 			} else {
877 				de[d].prn = prn;
878 				de[d].flags = flags;
879 				de[d].blkno = bno;
880 				de[d].len = len & 0x3FFFFFFF;
881 				d++;
882 			}
883 		}
884 	}
885 
886 	b_off = 0;
887 	for (i = 0; i < de_count; i++) {
888 		e_off = b_off + de[i].len;
889 		if (off < e_off) {
890 			bno = de[i].blkno + ((off - b_off) >> l2b);
891 			if ((*blkno = ud_xlate_to_daddr(
892 					de[i].prn, bno)) == 0) {
893 				return (1);
894 			}
895 			return (0);
896 		}
897 		b_off = e_off;
898 	}
899 	return (1);
900 }
901 
902 /*
903  * assume the buffer is big enough
904  * for the entire request
905  */
906 int32_t
907 read_file(uint32_t inode, uint8_t *buf, uint32_t count, uint64_t off)
908 {
909 	caddr_t addr;
910 	uint32_t bno, tcount;
911 
912 
913 	while (count) {
914 		if (get_blkno(inode, &bno, off) != 0) {
915 			return (1);
916 		}
917 		if ((addr = getblk(bno << l2b)) == NULL) {
918 			return (1);
919 		}
920 		if (bno == inode) {
921 			struct file_entry *fe;
922 			/*
923 			 * embedded file
924 			 */
925 			/* LINTED */
926 			fe = (struct file_entry *)addr;
927 			addr += 0xB0 + SWAP_32(fe->fe_len_ear);
928 			if (off >= SWAP_64(fe->fe_info_len)) {
929 				return (1);
930 			}
931 		}
932 		tcount = udfs.lbsize - (off & bmask);
933 		if (tcount > count) {
934 			tcount = count;
935 		}
936 		addr += off & bmask;
937 		(void) memcpy(buf, addr, tcount);
938 		count -= tcount;
939 		buf += tcount;
940 		off += tcount;
941 	}
942 	return (0);
943 }
944 
945 int32_t
946 get_fid(uint32_t inode, uint8_t *buf, uint64_t off)
947 {
948 	struct file_id *fid;
949 
950 	/* LINTED */
951 	fid = (struct file_id *)buf;
952 	if ((read_file(inode, buf, sizeof (struct file_id), off)) != 0) {
953 		return (1);
954 	}
955 
956 	if (ud_verify_tag(&fid->fid_tag, UD_FILE_ID_DESC, 0, 0, 1) != 0) {
957 		(void) fprintf(stdout,
958 			gettext("file_id tag does not verify off %llx\n"),
959 			off);
960 		return (1);
961 	}
962 
963 	if ((read_file(inode, buf, FID_LEN(fid), off)) != 0) {
964 		return (1);
965 	}
966 
967 	return (0);
968 }
969 
970 /*
971  * Path is absolute path
972  */
973 int32_t
974 inode_from_path(char *path, uint32_t *in, uint8_t *fl)
975 {
976 	char dname[1024];
977 	char fname[256];
978 	int32_t err;
979 	uint32_t dinode;
980 	struct tag *tag;
981 	uint8_t flags;
982 
983 	uint8_t buf[1024];
984 	uint64_t off;
985 	struct file_id *fid;
986 	uint8_t *addr;
987 
988 	if (strcmp(path, "/") == 0) {
989 		*fl = FID_DIR;
990 		if ((*in = ud_xlate_to_daddr(ricb_prn, ricb_loc)) == 0) {
991 			return (1);
992 		}
993 		return (0);
994 	}
995 
996 	(void) strcpy(dname, path);
997 	(void) strcpy(fname, basename(dname));
998 	(void) dirname(dname);
999 
1000 	if ((err = inode_from_path(dname, &dinode, &flags))  != 0) {
1001 		return (1);
1002 	}
1003 
1004 
1005 	/*
1006 	 * Check if dname is a directory
1007 	 */
1008 	if ((flags & FID_DIR) == 0) {
1009 		(void) fprintf(stdout,
1010 			gettext("Path %s is not a directory\n"), path);
1011 	}
1012 
1013 	/*
1014 	 * Search for the fname in the directory now
1015 	 */
1016 
1017 
1018 	off = 0;
1019 	/* LINTED */
1020 	fid = (struct file_id *)buf;
1021 	while (get_fid(dinode, buf, off) == 0) {
1022 		off += FID_LEN(fid);
1023 		if (fid->fid_flags & FID_DELETED) {
1024 			continue;
1025 		}
1026 		addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1];
1027 		if (fid->fid_flags & FID_PARENT) {
1028 			addr[0] = '.';
1029 			addr[1] = '.';
1030 			addr[2] = '\0';
1031 		} else {
1032 			addr[fid->fid_idlen] = '\0';
1033 		}
1034 		if (strcmp((caddr_t)addr, fname) == 0) {
1035 			*fl = fid->fid_flags;
1036 			if ((*in = ud_xlate_to_daddr(
1037 				SWAP_16(fid->fid_icb.lad_ext_prn),
1038 				SWAP_32(fid->fid_icb.lad_ext_loc))) == 0) {
1039 				return (1);
1040 			}
1041 			/* LINTED */
1042 			if ((tag = (struct tag *)getblk(*in << l2b)) == NULL) {
1043 				(void) fprintf(stdout,
1044 					gettext("Could not read block %x\n"),
1045 					*in);
1046 				return (1);
1047 			}
1048 			if (ud_verify_tag(tag, UD_FILE_ENTRY, 0, 0, 1) != 0) {
1049 				(void) fprintf(stdout,
1050 					gettext("Not a file entry(inode)"
1051 					" at %x\n"), *in);
1052 				return (1);
1053 			}
1054 			if (ud_verify_tag(tag, UD_FILE_ENTRY,
1055 					SWAP_32(tag->tag_loc), 1, 1) != 0) {
1056 				(void) fprintf(stdout,
1057 					gettext("CRC failed\n"));
1058 				return (1);
1059 			}
1060 
1061 			return (0);
1062 		}
1063 	}
1064 	return (err);
1065 }
1066 
1067 struct recu_dir {
1068 	struct recu_dir *next;
1069 	uint32_t inode;
1070 	char *nm;
1071 };
1072 
1073 void
1074 list(char *nm, uint32_t in, uint32_t fl)
1075 {
1076 	uint8_t buf[1024];
1077 	uint64_t off;
1078 	struct file_id *fid;
1079 	struct recu_dir *rd, *erd, *temp;
1080 	uint32_t iloc;
1081 
1082 	rd = erd = temp = NULL;
1083 	if (verify_inode(in << l2b, 4) == 0) {
1084 		(void) fprintf(stdout,
1085 			gettext("Inode is not a directory\n"));
1086 		return;
1087 	}
1088 
1089 	if (fl & 2) {
1090 		(void) printf("\n");
1091 		if (fl & 1) {
1092 			(void) fprintf(stdout,
1093 				gettext("i#: %x\t"), in);
1094 		}
1095 		(void) printf("%s\n", nm);
1096 	}
1097 
1098 	off = 0;
1099 	/* LINTED */
1100 	fid = (struct file_id *)buf;
1101 	while (get_fid(in, buf, off) == 0) {
1102 		off += FID_LEN(fid);
1103 		if (fid->fid_flags & FID_DELETED) {
1104 			continue;
1105 		}
1106 		iloc = ud_xlate_to_daddr(SWAP_16(fid->fid_icb.lad_ext_prn),
1107 				SWAP_32(fid->fid_icb.lad_ext_loc));
1108 		if (fl & 1) {
1109 			(void) fprintf(stdout,
1110 				gettext("i#: %x\t"), iloc);
1111 		}
1112 		if (fid->fid_flags & FID_PARENT) {
1113 			(void) fprintf(stdout,
1114 				gettext("..\n"));
1115 		} else {
1116 			int32_t i;
1117 			uint8_t *addr;
1118 
1119 			addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1];
1120 			for (i = 0; i < fid->fid_idlen - 1; i++)
1121 				(void) fprintf(stdout, "%c", addr[i]);
1122 			(void) fprintf(stdout, "\n");
1123 			if ((fid->fid_flags & FID_DIR) &&
1124 				(fl & 2)) {
1125 				temp = (struct recu_dir *)
1126 					malloc(sizeof (struct recu_dir));
1127 				if (temp == NULL) {
1128 					(void) fprintf(stdout,
1129 					gettext("Could not allocate memory\n"));
1130 				} else {
1131 					temp->next = NULL;
1132 					temp->inode = iloc;
1133 					temp->nm = malloc(strlen(nm) + 1 +
1134 						fid->fid_idlen + 1);
1135 					if (temp->nm != NULL) {
1136 						(void) strcpy(temp->nm, nm);
1137 						(void) strcat(temp->nm, "/");
1138 						(void) strncat(temp->nm,
1139 							(char *)addr,
1140 							fid->fid_idlen);
1141 					}
1142 					if (rd == NULL) {
1143 						erd = rd = temp;
1144 					} else {
1145 						erd->next = temp;
1146 						erd = temp;
1147 					}
1148 				}
1149 			}
1150 		}
1151 	}
1152 
1153 	while (rd != NULL) {
1154 		if (rd->nm != NULL) {
1155 			list(rd->nm, rd->inode, fl);
1156 		} else {
1157 			list(".", rd->inode, fl);
1158 		}
1159 		temp = rd;
1160 		rd = rd->next;
1161 		if (temp->nm) {
1162 			free(temp->nm);
1163 		}
1164 		free(temp);
1165 	}
1166 }
1167 
1168 void
1169 fill_pattern(uint32_t addr, uint32_t count, char *pattern)
1170 {
1171 	uint32_t beg, end, soff, lcount;
1172 	int32_t len = strlen(pattern);
1173 	caddr_t buf, p;
1174 
1175 	if (openflg == O_RDONLY) {
1176 		(void) fprintf(stdout,
1177 			gettext("Not run with -w flag\n"));
1178 		return;
1179 	}
1180 
1181 	if (count == 0) {
1182 		count = 1;
1183 	}
1184 	beg = addr;
1185 	end = addr + count * len;
1186 	soff = beg & (~bmask);
1187 	lcount = ((end + bmask) & (~bmask)) - soff;
1188 
1189 	inval_bufs();
1190 
1191 	buf = malloc(lcount);
1192 
1193 	if (llseek(fd, soff, SEEK_SET) != soff) {
1194 		(void) fprintf(stdout,
1195 			gettext("Seek failed fd %x off %llx errno %x\n"),
1196 			fd, soff, errno);
1197 		goto end;
1198 	}
1199 
1200 	if (read(fd, buf, lcount) != lcount) {
1201 		(void) fprintf(stdout,
1202 			gettext("Read failed fd %x off %llx errno %x\n"),
1203 			fd, soff, errno);
1204 		goto end;
1205 	}
1206 
1207 	p = buf + (addr & bmask);
1208 	while (count--) {
1209 		(void) strncpy(p, pattern, len);
1210 		p += len;
1211 	}
1212 
1213 	if (write(fd, buf, lcount) != lcount) {
1214 		(void) fprintf(stdout,
1215 			gettext("Write failed fd %x off %llx errno %x\n"),
1216 			fd, soff, errno);
1217 		goto end;
1218 	}
1219 end:
1220 	free(buf);
1221 }
1222 
1223 void
1224 dump_disk(uint32_t addr, uint32_t count, char *format)
1225 {
1226 	uint32_t beg, end, soff, lcount;
1227 	int32_t len, prperline, n;
1228 	uint8_t *buf, *p;
1229 	uint16_t *p_16;
1230 	uint32_t *p_32;
1231 
1232 	if (strlen(format) != 1) {
1233 		(void) fprintf(stdout,
1234 			gettext("Invalid command\n"));
1235 		return;
1236 	}
1237 	if (count == 0) {
1238 		count = 1;
1239 	}
1240 	switch (*format) {
1241 		case 'b' :
1242 			/* FALLTHROUGH */
1243 		case 'c' :
1244 			/* FALLTHROUGH */
1245 		case 'd' :
1246 			/* FALLTHROUGH */
1247 		case 'o' :
1248 			len = 1;
1249 			prperline = 16;
1250 			break;
1251 		case 'x' :
1252 			len = 2;
1253 			prperline = 8;
1254 			break;
1255 		case 'D' :
1256 			/* FALLTHROUGH */
1257 		case 'O' :
1258 			/* FALLTHROUGH */
1259 		case 'X' :
1260 			len = 4;
1261 			prperline = 4;
1262 			break;
1263 		default :
1264 			(void) fprintf(stdout,
1265 				gettext("Invalid format\n"));
1266 			return;
1267 	}
1268 
1269 	beg = addr;
1270 	end = addr + count * len;
1271 	soff = beg & (~bmask);
1272 	lcount = ((end + bmask) & (~bmask)) - soff;
1273 
1274 	inval_bufs();
1275 
1276 	buf = malloc(lcount);
1277 	if (llseek(fd, soff, SEEK_SET) != soff) {
1278 		(void) fprintf(stdout,
1279 			gettext("Seek failed fd %x off %llx errno %x\n"),
1280 			fd, soff, errno);
1281 		goto end;
1282 	}
1283 
1284 	if (read(fd, buf, lcount) != lcount) {
1285 		(void) fprintf(stdout,
1286 			gettext("Read failed fd %x off %llx errno %x\n"),
1287 			fd, soff, errno);
1288 		goto end;
1289 	}
1290 	p = buf + (addr & bmask);
1291 	/* LINTED */
1292 	p_16 = (uint16_t *)p;
1293 	/* LINTED */
1294 	p_32 = (uint32_t *)p;
1295 	n = 0;
1296 	while (n < count) {
1297 		switch (*format) {
1298 			case 'b' :
1299 				(void) fprintf(stdout,
1300 					"%4x ", *((uint8_t *)p));
1301 				break;
1302 			case 'c' :
1303 				(void) fprintf(stdout,
1304 					"%4c ", *((uint8_t *)p));
1305 				break;
1306 			case 'd' :
1307 				(void) fprintf(stdout,
1308 					"%4d ", *((uint8_t *)p));
1309 				break;
1310 			case 'o' :
1311 				(void) fprintf(stdout,
1312 					"%4o ", *((uint8_t *)p));
1313 				break;
1314 			case 'x' :
1315 				(void) fprintf(stdout,
1316 					"%8x ", *p_16);
1317 				break;
1318 			case 'D' :
1319 				(void) fprintf(stdout,
1320 					"%16d ", *p_32);
1321 				break;
1322 			case 'O' :
1323 				(void) fprintf(stdout,
1324 					"%16o ", *p_32);
1325 				break;
1326 			case 'X' :
1327 				(void) fprintf(stdout,
1328 					"%16x ", *p_32);
1329 				break;
1330 		}
1331 		p += len;
1332 		n++;
1333 		if ((n % prperline) == 0) {
1334 			(void) fprintf(stdout, "\n");
1335 		}
1336 	}
1337 	if (n % prperline) {
1338 		(void) fprintf(stdout, "\n");
1339 	}
1340 end:
1341 	free(buf);
1342 }
1343 
1344 void
1345 find_it(char *dir, char *name, uint32_t in, uint32_t fl)
1346 {
1347 	uint8_t buf[1024], *addr;
1348 	uint64_t off;
1349 	struct file_id *fid;
1350 	uint32_t iloc, d_in;
1351 	uint8_t d_fl;
1352 	struct recu_dir *rd, *erd, *temp;
1353 
1354 	rd = erd = temp = NULL;
1355 
1356 	if (inode_from_path(dir, &d_in, &d_fl) != 0) {
1357 		(void) fprintf(stdout,
1358 			gettext("Could not find directory %s"), dir);
1359 		return;
1360 	}
1361 
1362 	if ((d_fl & FID_DIR) == 0) {
1363 		(void) fprintf(stdout,
1364 			gettext("Path %s is not a directory\n"), dir);
1365 		return;
1366 	}
1367 
1368 	if (verify_inode(d_in << l2b, 4) == 0) {
1369 		(void) fprintf(stdout,
1370 			gettext("Inode is not a directory\n"));
1371 		return;
1372 	}
1373 
1374 	off = 0;
1375 	/* LINTED */
1376 	fid = (struct file_id *)buf;
1377 	while (get_fid(d_in, buf, off) == 0) {
1378 		off += FID_LEN(fid);
1379 		if ((fid->fid_flags & FID_DELETED) ||
1380 			(fid->fid_flags & FID_PARENT)) {
1381 			continue;
1382 		}
1383 
1384 		iloc = ud_xlate_to_daddr(SWAP_16(fid->fid_icb.lad_ext_prn),
1385 				SWAP_32(fid->fid_icb.lad_ext_loc));
1386 		addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1];
1387 		if (((fl & 4) && (in == iloc)) ||
1388 		((fl & 2) && (strcmp(name, (char *)addr) == 0))) {
1389 			(void) printf("%s %x %s\n", dir, iloc, addr);
1390 		}
1391 
1392 		if (fid->fid_flags & FID_DIR) {
1393 			temp = (struct recu_dir *)
1394 				malloc(sizeof (struct recu_dir));
1395 			if (temp == NULL) {
1396 				(void) fprintf(stdout,
1397 				gettext("Could not allocate memory\n"));
1398 			} else {
1399 				temp->next = NULL;
1400 				temp->inode = iloc;
1401 				temp->nm = malloc(strlen(dir) + 1 +
1402 					fid->fid_idlen + 1);
1403 				if (temp->nm != NULL) {
1404 					(void) strcpy(temp->nm, dir);
1405 					(void) strcat(temp->nm, "/");
1406 					(void) strncat(temp->nm, (char *)addr,
1407 						fid->fid_idlen);
1408 				} else {
1409 					(void) fprintf(stdout, gettext(
1410 					"Could not allocate memory\n"));
1411 				}
1412 				if (rd == NULL) {
1413 					erd = rd = temp;
1414 				} else {
1415 					erd->next = temp;
1416 					erd = temp;
1417 				}
1418 			}
1419 		}
1420 	}
1421 
1422 	while (rd != NULL) {
1423 		if (rd->nm != NULL) {
1424 			find_it(rd->nm, name, in, fl);
1425 		}
1426 		temp = rd;
1427 		rd = rd->next;
1428 		if (temp->nm) {
1429 			free(temp->nm);
1430 		}
1431 		free(temp);
1432 	}
1433 }
1434