xref: /illumos-gate/usr/src/cmd/fs.d/udfs/common/ud_lib.c (revision 22028508fd28d36ff74dc02c5774a8ba1f0db045)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <malloc.h>
29 #include <unistd.h>
30 #include <strings.h>
31 #include <errno.h>
32 #include <libintl.h>
33 #include <libgen.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/int_types.h>
37 #include <sys/dkio.h>
38 #include <sys/cdio.h>
39 #include <sys/vtoc.h>
40 #include <sys/stat.h>
41 #include <sys/param.h>
42 #include <sys/fs/udf_volume.h>
43 #include "ud_lib.h"
44 
45 extern char *getfullrawname(char *);
46 
47 static int32_t ud_get_ecma_ver(ud_handle_t, uint32_t);
48 static int32_t ud_get_fs_bsize(ud_handle_t, uint32_t, uint32_t *);
49 static int32_t ud_parse_fill_vds(ud_handle_t, struct vds *, uint32_t, uint32_t);
50 static int32_t	ud_read_and_translate_lvd(ud_handle_t, uint32_t, uint32_t);
51 static int32_t ud_get_latest_lvid(ud_handle_t, uint32_t, uint32_t);
52 static int32_t	ud_get_latest_fsd(ud_handle_t, uint16_t, uint32_t, uint32_t);
53 
54 static uint16_t ud_crc(uint8_t *, int32_t);
55 static int32_t UdfTxName(uint16_t *, int32_t);
56 static int32_t UncompressUnicode(int32_t, uint8_t *, uint16_t *);
57 static int32_t ud_compressunicode(int32_t, int32_t, uint16_t *, uint8_t *);
58 static int32_t ud_convert2utf8(uint8_t *, uint8_t *, int32_t);
59 static int32_t ud_convert2utf16(uint8_t *, uint8_t *, int32_t);
60 
61 
62 int
63 ud_init(int fd, ud_handle_t *hp)
64 {
65 	struct ud_handle *h;
66 
67 	if ((h = calloc(1, sizeof (struct ud_handle))) == NULL) {
68 		return (ENOMEM);
69 	}
70 	h->fd = fd;
71 	*hp = h;
72 	return (0);
73 }
74 
75 void
76 ud_fini(ud_handle_t h)
77 {
78 	free(h);
79 }
80 
81 /* ARGSUSED */
82 int32_t
83 ud_open_dev(ud_handle_t h, char *special, uint32_t flags)
84 {
85 	char *temp;
86 	struct stat i_stat, r_stat;
87 
88 	(void) bzero(&i_stat, sizeof (struct stat));
89 	(void) bzero(&r_stat, sizeof (struct stat));
90 
91 	temp = special;
92 	/*
93 	 * Get the stat structure
94 	 */
95 	if (stat(special, &i_stat) == 0) {
96 		if ((i_stat.st_mode & S_IFMT) == S_IFBLK) {
97 
98 			/*
99 			 * Block device try to convert to raw device
100 			 */
101 
102 			temp = getfullrawname(special);
103 
104 			/*
105 			 * Stat the converted device name and verify
106 			 * both the raw and block device belong to
107 			 * the same device
108 			 */
109 			if (stat(temp, &r_stat) < 0) {
110 				temp = special;
111 			} else {
112 				if (((r_stat.st_mode & S_IFMT) == S_IFBLK) ||
113 					(r_stat.st_rdev != i_stat.st_rdev)) {
114 					temp = special;
115 				}
116 			}
117 		}
118 	}
119 
120 	/*
121 	 * Now finally open the device
122 	 */
123 	h->fd = open(temp, flags);
124 
125 	return (h->fd);
126 }
127 
128 /* ARGSUSED */
129 void
130 ud_close_dev(ud_handle_t h)
131 {
132 	/*
133 	 * Too simple Just close it
134 	 */
135 	(void) close(h->fd);
136 }
137 
138 int32_t
139 ud_read_dev(ud_handle_t h, uint64_t offset, uint8_t *buf, uint32_t count)
140 {
141 	/*
142 	 * Seek to the given offset
143 	 */
144 	if (lseek(h->fd, offset, SEEK_SET) == -1) {
145 		return (1);
146 	}
147 
148 	/*
149 	 * Read the required number of bytes
150 	 */
151 	if (read(h->fd, buf, count) != count) {
152 		return (1);
153 	}
154 	return (0);
155 }
156 
157 int32_t
158 ud_write_dev(ud_handle_t h, uint64_t offset, uint8_t *buf, uint32_t count)
159 {
160 	/*
161 	 * Seek to the given offset
162 	 */
163 	if (lseek(h->fd, offset, SEEK_SET) == -1) {
164 		return (1);
165 	}
166 
167 	/*
168 	 * Read the appropriate number of bytes
169 	 */
170 	if (write(h->fd, buf, count) != count) {
171 		return (1);
172 	}
173 	return (0);
174 }
175 
176 /* ----- BEGIN Read and translate the on disk VDS to IN CORE format -------- */
177 
178 int32_t
179 ud_fill_udfs_info(ud_handle_t h)
180 {
181 	struct	anch_vol_desc_ptr	*avdp = NULL;
182 	uint32_t			offset = 0;
183 
184 	if (ioctl(h->fd, CDROMREADOFFSET, &offset) == -1) {
185 		offset = 0;
186 	}
187 
188 	h->udfs.flags = INVALID_UDFS;
189 
190 	h->udfs.ecma_version = ud_get_ecma_ver(h, offset);
191 	if (h->udfs.ecma_version == UD_ECMA_UNKN) {
192 		return (1);
193 	}
194 
195 	h->udfs.lbsize = ud_get_fs_bsize(h, offset, &h->udfs.avdp_loc);
196 	if (h->udfs.lbsize == 0) {
197 		return (2);
198 	}
199 
200 	h->udfs.avdp_len = lb_roundup(512, h->udfs.lbsize);
201 
202 
203 	if ((avdp = (struct anch_vol_desc_ptr *)
204 			malloc(h->udfs.lbsize)) == NULL) {
205 		return (3);
206 	}
207 	if (ud_read_dev(h, h->udfs.avdp_loc * h->udfs.lbsize,
208 			(uint8_t *)avdp, h->udfs.lbsize) != 0) {
209 		free(avdp);
210 		return (4);
211 	}
212 	if (ud_verify_tag(h, &avdp->avd_tag, UD_ANCH_VOL_DESC,
213 			h->udfs.avdp_loc, 1, 0) != 0) {
214 		free(avdp);
215 		return (5);
216 	}
217 
218 	h->udfs.mvds_loc = SWAP_32(avdp->avd_main_vdse.ext_loc);
219 	h->udfs.mvds_len = SWAP_32(avdp->avd_main_vdse.ext_len);
220 
221 	h->udfs.rvds_loc = SWAP_32(avdp->avd_res_vdse.ext_loc);
222 	h->udfs.rvds_len = SWAP_32(avdp->avd_res_vdse.ext_len);
223 
224 	free(avdp);
225 
226 	/*
227 	 * get information from mvds and rvds
228 	 */
229 	if (ud_parse_fill_vds(h, &h->udfs.mvds,
230 			h->udfs.mvds_loc, h->udfs.mvds_len) == 0) {
231 		h->udfs.flags |= VALID_MVDS;
232 	}
233 	if (ud_parse_fill_vds(h, &h->udfs.rvds,
234 			h->udfs.rvds_loc, h->udfs.rvds_len) == 0) {
235 		h->udfs.flags |= VALID_RVDS;
236 	}
237 
238 	if ((h->udfs.flags & (VALID_MVDS | VALID_RVDS)) == 0) {
239 		return (6);
240 	}
241 
242 	/*
243 	 * If we are here we have
244 	 * a valid Volume Descriptor Seqence
245 	 * Read and understand lvd
246 	 */
247 	if (h->udfs.flags & VALID_MVDS) {
248 		if (ud_read_and_translate_lvd(h, h->udfs.mvds.lvd_loc,
249 				h->udfs.mvds.lvd_len) != 0) {
250 			return (7);
251 		}
252 	} else {
253 		if (ud_read_and_translate_lvd(h, h->udfs.rvds.lvd_loc,
254 				h->udfs.rvds.lvd_len) != 0) {
255 			return (8);
256 		}
257 	}
258 
259 	h->udfs.flags |= VALID_UDFS;
260 
261 	return (0);
262 }
263 
264 static int32_t
265 ud_get_ecma_ver(ud_handle_t h, uint32_t offset)
266 {
267 	uint8_t *buf;
268 	uint64_t off;
269 	uint64_t end_off;
270 	struct nsr_desc *ndsc;
271 	uint32_t ecma_ver = UD_ECMA_UNKN;
272 
273 	/*
274 	 * Allocate a buffer of size UD_VOL_REC_BSZ
275 	 */
276 	if ((buf = (uint8_t *)malloc(UD_VOL_REC_BSZ)) == NULL) {
277 
278 		/*
279 		 * Uh could not even allocate this much
280 		 */
281 		goto end;
282 	}
283 
284 	/*
285 	 * Start from 32k and keep reading 2k blocks we
286 	 * should be able to find NSR if we have one by 256 * 2k bytes
287 	 */
288 	off = offset * 2048 + UD_VOL_REC_START;
289 	end_off = offset * 2048 + UD_VOL_REC_END;
290 	for (; off < end_off; off += UD_VOL_REC_BSZ) {
291 
292 		if (ud_read_dev(h, off, buf, UD_VOL_REC_BSZ) == 0) {
293 
294 			ndsc = (struct nsr_desc *)buf;
295 			/*
296 			 * Is this either NSR02 or NSR03
297 			 */
298 			if ((ndsc->nsr_str_type == 0) &&
299 				(ndsc->nsr_ver == 1) &&
300 				(ndsc->nsr_id[0] == 'N') &&
301 				(ndsc->nsr_id[1] == 'S') &&
302 				(ndsc->nsr_id[2] == 'R') &&
303 				(ndsc->nsr_id[3] == '0') &&
304 					((ndsc->nsr_id[4] == '2') ||
305 					(ndsc->nsr_id[4] == '3'))) {
306 
307 				(void) strncpy((char *)h->udfs.ecma_id,
308 					(char *)ndsc->nsr_id, 5);
309 
310 				switch (ndsc->nsr_id[4]) {
311 				case '2' :
312 
313 					/*
314 					 * ECMA 167/2
315 					 */
316 					ecma_ver = UD_ECMA_VER2;
317 					goto end;
318 				case '3' :
319 
320 					/*
321 					 * ECMA 167/3
322 					 */
323 					ecma_ver = UD_ECMA_VER3;
324 					goto end;
325 				}
326 			}
327 		}
328 	}
329 
330 end:
331 	/*
332 	 * Cleanup
333 	 */
334 	free(buf);
335 	return (ecma_ver);
336 }
337 
338 static uint32_t last_block_index[] = {0, 0, 256, 2, 2 + 256,
339 		150, 150 + 256, 152, 152 + 256};
340 
341 static int32_t
342 ud_get_fs_bsize(ud_handle_t h, uint32_t offset, uint32_t *avd_loc)
343 {
344 	uint64_t off;
345 	int32_t index, bsize, shift, end_index;
346 	uint32_t num_blocks, sub_blk;
347 	uint8_t *buf = NULL;
348 	struct anch_vol_desc_ptr *avdp;
349 
350 	if ((buf = (uint8_t *)malloc(MAXBSIZE)) == NULL) {
351 		return (0);
352 	}
353 
354 	/*
355 	 * If we could figure out the last block
356 	 * search at 256, N, N - 256 blocks
357 	 * otherwise just check at 256
358 	 */
359 	if (ud_get_num_blks(h, &num_blocks) != 0) {
360 		end_index = 1;
361 		num_blocks = 0;
362 	} else {
363 		end_index = sizeof (last_block_index) / 4;
364 	}
365 
366 	for (index = 0; index < end_index; index++) {
367 		sub_blk = last_block_index[index];
368 
369 		/*
370 		 * Start guessing from DEV_BSIZE to MAXBSIZE
371 		 */
372 		for (bsize = DEV_BSIZE, shift = 0;
373 			bsize <= MAXBSIZE; bsize <<= 1, shift++) {
374 
375 			if (index == 0) {
376 
377 				/*
378 				 * Check if we atleast have 256 of bsize
379 				 * blocks on the device
380 				 */
381 				if ((end_index == 0) ||
382 					(num_blocks > (256 << shift))) {
383 					*avd_loc = 256;
384 					if (bsize <= 2048) {
385 						*avd_loc +=
386 							offset * 2048 / bsize;
387 					} else {
388 						*avd_loc +=
389 							offset / (bsize / 2048);
390 					}
391 				} else {
392 					continue;
393 				}
394 			} else {
395 				/*
396 				 * Calculate the bsize avd block
397 				 */
398 				if ((num_blocks) &&
399 					(num_blocks > (sub_blk << shift))) {
400 					*avd_loc = (num_blocks >> shift) -
401 						sub_blk;
402 				} else {
403 					continue;
404 				}
405 			}
406 
407 			off = (uint64_t)*avd_loc * bsize;
408 
409 			/*
410 			 * Read bsize bytes at off
411 			 */
412 			if (ud_read_dev(h, off, buf, bsize) != 0) {
413 				continue;
414 			}
415 
416 			/*
417 			 * Check if we have a Anchor Volume Descriptor here
418 			 */
419 
420 			/* LINTED */
421 			avdp = (struct anch_vol_desc_ptr *)buf;
422 			if (ud_verify_tag(h, &avdp->avd_tag,
423 				UD_ANCH_VOL_DESC, *avd_loc, 1, 0) != 0) {
424 				continue;
425 			}
426 			goto end;
427 		}
428 	}
429 
430 end:
431 	if (bsize > MAXBSIZE) {
432 		bsize = 0;
433 		*avd_loc = 0;
434 	}
435 	free(buf);
436 	return (bsize);
437 }
438 
439 static int32_t
440 ud_parse_fill_vds(ud_handle_t h, struct vds *v,
441 	uint32_t vds_loc, uint32_t vds_len)
442 {
443 	uint8_t *addr, *taddr, *eaddr;
444 	uint16_t id;
445 	int32_t i;
446 	uint64_t off;
447 	struct tag *tag;
448 	struct pri_vol_desc *pvd;
449 	struct log_vol_desc *lvd;
450 	struct vol_desc_ptr *vds;
451 	struct unall_spc_desc *usd;
452 
453 begin:
454 	if ((addr = (uint8_t *)malloc(vds_len)) == NULL) {
455 		return (1);
456 	}
457 
458 	off = vds_loc * h->udfs.lbsize;
459 	if (ud_read_dev(h, off, addr, vds_len) != 0) {
460 		goto end;
461 	}
462 
463 	for (taddr = addr, eaddr = addr + h->udfs.mvds_len; taddr < eaddr;
464 			taddr += h->udfs.lbsize, vds_loc ++) {
465 
466 		/* LINTED */
467 		tag = (struct tag *)taddr;
468 		id = SWAP_16(tag->tag_id);
469 		/*
470 		 * If you cannot verify the tag just skip it
471 		 * This is not a fatal error
472 		 */
473 		if (ud_verify_tag(h, tag, id, vds_loc, 1, 0) != 0) {
474 			continue;
475 		}
476 		switch (id) {
477 		case UD_PRI_VOL_DESC :
478 
479 			/*
480 			 * Primary Volume Descriptor
481 			 */
482 			/* LINTED */
483 			pvd = (struct pri_vol_desc *)taddr;
484 			if ((v->pvd_len == 0) ||
485 				(SWAP_32(pvd->pvd_vdsn) > v->pvd_vdsn)) {
486 				v->pvd_vdsn = SWAP_32(pvd->pvd_vdsn);
487 				v->pvd_loc = vds_loc;
488 				v->pvd_len = h->udfs.lbsize;
489 			}
490 			break;
491 		case UD_VOL_DESC_PTR :
492 
493 			/*
494 			 * Curent sequence is continued from
495 			 * the location pointed by vdp
496 			 */
497 			/* LINTED */
498 			vds = (struct vol_desc_ptr *)taddr;
499 
500 			if (SWAP_32(vds->vdp_nvdse.ext_len) != 0) {
501 				vds_loc = SWAP_32(vds->vdp_nvdse.ext_loc);
502 				vds_len = SWAP_32(vds->vdp_nvdse.ext_len);
503 				free(addr);
504 				goto begin;
505 			}
506 			break;
507 		case UD_IMPL_USE_DESC :
508 
509 			/*
510 			 * Implementation Use Volume Descriptor
511 			 */
512 			v->iud_loc = vds_loc;
513 			v->iud_len = lb_roundup(512, h->udfs.lbsize);
514 			break;
515 		case UD_PART_DESC :
516 			{
517 				struct ud_part *p;
518 				struct phdr_desc *ph;
519 				struct part_desc *pd;
520 
521 				/*
522 				 * Partition Descriptor
523 				 */
524 				/* LINTED */
525 				pd = (struct part_desc *)taddr;
526 
527 				for (i = 0; i < h->n_parts; i++) {
528 					p = &h->part[i];
529 
530 					if ((SWAP_16(pd->pd_pnum) ==
531 							p->udp_number) &&
532 						(SWAP_32(pd->pd_vdsn) >
533 							p->udp_seqno)) {
534 						break;
535 					}
536 				}
537 
538 				v->part_loc[i] = vds_loc;
539 				v->part_len[i] =
540 					lb_roundup(512, h->udfs.lbsize);
541 
542 				p = &h->part[i];
543 				p->udp_number = SWAP_16(pd->pd_pnum);
544 				p->udp_seqno = SWAP_32(pd->pd_vdsn);
545 				p->udp_access = SWAP_32(pd->pd_acc_type);
546 				p->udp_start = SWAP_32(pd->pd_part_start);
547 				p->udp_length = SWAP_32(pd->pd_part_length);
548 
549 				/* LINTED */
550 				ph = (struct phdr_desc *)pd->pd_pc_use;
551 				if (ph->phdr_ust.sad_ext_len) {
552 			p->udp_flags = UDP_SPACETBLS;
553 			p->udp_unall_loc = SWAP_32(ph->phdr_ust.sad_ext_loc);
554 			p->udp_unall_len = SWAP_32(ph->phdr_ust.sad_ext_len);
555 			p->udp_freed_loc = SWAP_32(ph->phdr_fst.sad_ext_loc);
556 			p->udp_freed_len = SWAP_32(ph->phdr_fst.sad_ext_len);
557 				} else {
558 			p->udp_flags = UDP_BITMAPS;
559 			p->udp_unall_loc = SWAP_32(ph->phdr_usb.sad_ext_loc);
560 			p->udp_unall_len = SWAP_32(ph->phdr_usb.sad_ext_len);
561 			p->udp_freed_loc = SWAP_32(ph->phdr_fsb.sad_ext_loc);
562 			p->udp_freed_len = SWAP_32(ph->phdr_fsb.sad_ext_len);
563 				}
564 
565 				if (i == h->n_parts) {
566 					h->n_parts ++;
567 				}
568 			}
569 			break;
570 		case UD_LOG_VOL_DESC :
571 
572 			/*
573 			 * Logical Volume Descriptor
574 			 */
575 			/* LINTED */
576 			lvd = (struct log_vol_desc *)taddr;
577 			if ((v->lvd_len == 0) ||
578 				(SWAP_32(lvd->lvd_vdsn) > v->lvd_vdsn)) {
579 				v->lvd_vdsn = SWAP_32(lvd->lvd_vdsn);
580 				v->lvd_loc = vds_loc;
581 				v->lvd_len = ((uint32_t)
582 					&((struct log_vol_desc *)0)->lvd_pmaps);
583 				v->lvd_len =
584 					lb_roundup(v->lvd_len, h->udfs.lbsize);
585 			}
586 			break;
587 		case UD_UNALL_SPA_DESC :
588 
589 			/*
590 			 * Unallocated Space Descriptor
591 			 */
592 			/* LINTED */
593 			usd = (struct unall_spc_desc *)taddr;
594 			v->usd_loc = vds_loc;
595 			v->usd_len = ((uint32_t)
596 			&((unall_spc_desc_t *)0)->ua_al_dsc) +
597 				SWAP_32(usd->ua_nad) *
598 				sizeof (struct extent_ad);
599 			v->usd_len = lb_roundup(v->usd_len, h->udfs.lbsize);
600 			break;
601 		case UD_TERM_DESC :
602 			/*
603 			 * Success fully completed
604 			 */
605 			goto end;
606 		default :
607 			/*
608 			 * If you donot undetstand any tag just skip
609 			 * it. This is not a fatal error
610 			 */
611 			break;
612 		}
613 	}
614 
615 end:
616 	free(addr);
617 	if ((v->pvd_len == 0) ||
618 		(v->part_len[0] == 0) ||
619 		(v->lvd_len == 0)) {
620 		return (1);
621 	}
622 
623 	return (0);
624 }
625 
626 static int32_t
627 ud_read_and_translate_lvd(ud_handle_t h, uint32_t lvd_loc, uint32_t lvd_len)
628 {
629 	caddr_t addr;
630 	uint16_t fsd_prn;
631 	uint32_t fsd_loc, fsd_len;
632 	uint32_t lvds_loc, lvds_len;
633 	uint64_t off;
634 	struct log_vol_desc *lvd = NULL;
635 
636 	int32_t max_maps, i, mp_sz, index;
637 	struct ud_map *m;
638 	struct pmap_hdr *ph;
639 	struct pmap_typ1 *typ1;
640 	struct pmap_typ2 *typ2;
641 
642 	if (lvd_len == 0) {
643 		return (1);
644 	}
645 
646 	if ((lvd = (struct log_vol_desc *)
647 			malloc(lvd_len)) == NULL) {
648 		return (1);
649 	}
650 
651 	off = lvd_loc * h->udfs.lbsize;
652 	if (ud_read_dev(h, off, (uint8_t *)lvd, lvd_len) != 0) {
653 		free(lvd);
654 		return (1);
655 	}
656 
657 	if (ud_verify_tag(h, &lvd->lvd_tag, UD_LOG_VOL_DESC,
658 			lvd_loc, 1, 0) != 0) {
659 		free(lvd);
660 		return (1);
661 	}
662 
663 	/*
664 	 * Take care of maps
665 	 */
666 	max_maps = SWAP_32(lvd->lvd_num_pmaps);
667 	ph = (struct pmap_hdr *)lvd->lvd_pmaps;
668 	for (h->n_maps = index = 0; index < max_maps; index++) {
669 		m = &h->maps[h->n_maps];
670 		switch (ph->maph_type) {
671 		case MAP_TYPE1 :
672 
673 			/* LINTED */
674 			typ1 = (struct pmap_typ1 *)ph;
675 
676 			m->udm_flags = UDM_MAP_NORM;
677 			m->udm_vsn = SWAP_16(typ1->map1_vsn);
678 			m->udm_pn = SWAP_16(typ1->map1_pn);
679 			h->n_maps++;
680 			break;
681 
682 		case MAP_TYPE2 :
683 
684 			/* LINTED */
685 			typ2 = (struct pmap_typ2 *)ph;
686 
687 			if (strncmp(typ2->map2_pti.reg_id,
688 					UDF_VIRT_PART, 23) == 0) {
689 
690 				m->udm_flags = UDM_MAP_VPM;
691 				m->udm_vsn = SWAP_16(typ2->map2_vsn);
692 				m->udm_pn = SWAP_16(typ2->map2_pn);
693 			} else if (strncmp(typ2->map2_pti.reg_id,
694 					UDF_SPAR_PART, 23) == 0) {
695 
696 				if ((SWAP_16(typ2->map2_pl) != 32) ||
697 						(typ2->map2_nst < 1) ||
698 						(typ2->map2_nst > 4)) {
699 					break;
700 				}
701 				m->udm_flags = UDM_MAP_SPM;
702 				m->udm_vsn = SWAP_16(typ2->map2_vsn);
703 				m->udm_pn = SWAP_16(typ2->map2_pn);
704 
705 				m->udm_plen = SWAP_16(typ2->map2_pl);
706 				m->udm_nspm = typ2->map2_nst;
707 				m->udm_spsz = SWAP_32(typ2->map2_sest);
708 
709 				mp_sz = lb_roundup(m->udm_spsz, h->udfs.lbsize);
710 
711 				if ((addr = malloc(mp_sz * m->udm_nspm)) ==
712 						NULL) {
713 					break;
714 				}
715 
716 				for (i = 0; i < m->udm_nspm; i++) {
717 					m->udm_loc[i] =
718 						SWAP_32(typ2->map2_st[index]);
719 					m->udm_spaddr[i] = addr + i * mp_sz;
720 
721 					off = m->udm_loc[i] * h->udfs.lbsize;
722 					if (ud_read_dev(h, off,
723 						(uint8_t *)m->udm_spaddr[i],
724 							mp_sz) != 0) {
725 						m->udm_spaddr[i] = NULL;
726 						continue;
727 					}
728 				}
729 			}
730 			h->n_maps++;
731 		default :
732 			break;
733 		}
734 		ph = (struct pmap_hdr *)(((uint8_t *)h) + ph->maph_length);
735 	}
736 
737 	lvds_loc = SWAP_32(lvd->lvd_int_seq_ext.ext_loc);
738 	lvds_len = SWAP_32(lvd->lvd_int_seq_ext.ext_len);
739 
740 	fsd_prn = SWAP_16(lvd->lvd_lvcu.lad_ext_prn);
741 	fsd_loc = SWAP_32(lvd->lvd_lvcu.lad_ext_loc);
742 	fsd_len = SWAP_32(lvd->lvd_lvcu.lad_ext_len);
743 
744 	free(lvd);
745 
746 	/*
747 	 * Get the latest LVID
748 	 */
749 	if (ud_get_latest_lvid(h, lvds_loc, lvds_len) != 0) {
750 		return (1);
751 	}
752 
753 	if (ud_get_latest_fsd(h, fsd_prn, fsd_loc, fsd_len) != 0) {
754 		return (1);
755 	}
756 
757 	return (0);
758 }
759 
760 static int32_t
761 ud_get_latest_lvid(ud_handle_t h, uint32_t lvds_loc, uint32_t lvds_len)
762 {
763 	uint8_t *addr, *taddr, *eaddr;
764 	uint16_t id;
765 	uint64_t off;
766 	struct tag *tag;
767 	struct log_vol_int_desc *lvid;
768 
769 begin:
770 	if ((addr = (uint8_t *)malloc(lvds_len)) == NULL) {
771 		return (1);
772 	}
773 
774 	off = lvds_loc * h->udfs.lbsize;
775 	if (ud_read_dev(h, off, addr, lvds_len) != 0) {
776 		goto end;
777 	}
778 
779 	for (taddr = addr, eaddr = addr + h->udfs.mvds_len; taddr < eaddr;
780 			taddr += h->udfs.lbsize, lvds_loc ++) {
781 
782 		/* LINTED */
783 		tag = (struct tag *)taddr;
784 		id = SWAP_16(tag->tag_id);
785 		/*
786 		 * If you cannot verify the tag just skip it
787 		 * This is not a fatal error
788 		 */
789 		if (ud_verify_tag(h, tag, id, lvds_loc, 1, 0) != 0) {
790 			continue;
791 		}
792 		switch (id) {
793 		case UD_LOG_VOL_INT :
794 
795 			/*
796 			 * Logical Volume Integrity Descriptor
797 			 */
798 			/* LINTED */
799 			lvid = (struct log_vol_int_desc *)taddr;
800 			h->udfs.lvid_loc = lvds_loc;
801 			h->udfs.lvid_len = ((uint32_t)
802 			&((struct log_vol_int_desc *)0)->lvid_fst) +
803 				SWAP_32(lvid->lvid_npart) * 8 +
804 				SWAP_32(lvid->lvid_liu);
805 			h->udfs.lvid_len = lb_roundup(h->udfs.lvid_len,
806 				h->udfs.lbsize);
807 
808 			/*
809 			 * It seems we have a next integrity
810 			 * sequence
811 			 */
812 			if (SWAP_32(lvid->lvid_nie.ext_len) != 0) {
813 				free(addr);
814 				lvds_loc = SWAP_32(lvid->lvid_nie.ext_loc);
815 				lvds_len = SWAP_32(lvid->lvid_nie.ext_len);
816 				goto begin;
817 			}
818 			goto end;
819 		case UD_TERM_DESC :
820 
821 			/*
822 			 * Success fully completed
823 			 */
824 				goto end;
825 		default :
826 			/*
827 			 * If you donot undetstand any tag just skip
828 			 * it. This is not a fatal error
829 			 */
830 			break;
831 		}
832 	}
833 end:
834 	free(addr);
835 	if (h->udfs.lvid_len == 0) {
836 		return (1);
837 	}
838 	return (0);
839 }
840 
841 static int32_t
842 ud_get_latest_fsd(ud_handle_t h, uint16_t fsd_prn,
843 	uint32_t fsd_loc, uint32_t fsd_len)
844 {
845 	uint8_t *addr, *taddr, *eaddr;
846 	uint16_t id;
847 	uint64_t off;
848 	uint32_t fsds_loc, fsds_len;
849 	struct tag *tag;
850 	struct file_set_desc *fsd;
851 	uint32_t old_fsn = 0;
852 
853 begin:
854 	h->udfs.fsds_prn = fsd_prn;
855 	h->udfs.fsds_loc = fsd_loc;
856 	h->udfs.fsds_len = fsd_len;
857 
858 	fsds_loc = ud_xlate_to_daddr(h, fsd_prn, fsd_loc);
859 	fsds_len = lb_roundup(fsd_len, h->udfs.lbsize);
860 
861 	if ((addr = (uint8_t *)malloc(fsds_len)) == NULL) {
862 		return (1);
863 	}
864 
865 	off = fsds_loc * h->udfs.lbsize;
866 	if (ud_read_dev(h, off, addr, fsds_len) != 0) {
867 		goto end;
868 	}
869 
870 	for (taddr = addr, eaddr = addr + h->udfs.mvds_len; taddr < eaddr;
871 			taddr += h->udfs.lbsize, fsds_loc ++) {
872 
873 		/* LINTED */
874 		tag = (struct tag *)taddr;
875 		id = SWAP_16(tag->tag_id);
876 		/*
877 		 * If you cannot verify the tag just skip it
878 		 * This is not a fatal error
879 		 */
880 		if (ud_verify_tag(h, tag, id, fsds_loc, 1, 0) != 0) {
881 			continue;
882 		}
883 		switch (id) {
884 		case UD_FILE_SET_DESC :
885 			/* LINTED */
886 			fsd = (struct file_set_desc *)taddr;
887 			if ((h->udfs.fsd_len == 0) ||
888 				(SWAP_32(fsd->fsd_fs_no) > old_fsn)) {
889 				old_fsn = SWAP_32(fsd->fsd_fs_no);
890 				h->udfs.fsd_loc = fsds_loc;
891 				h->udfs.fsd_len = lb_roundup(512,
892 					h->udfs.lbsize);
893 				h->udfs.ricb_prn =
894 					SWAP_16(fsd->fsd_root_icb.lad_ext_prn);
895 				h->udfs.ricb_loc =
896 					SWAP_32(fsd->fsd_root_icb.lad_ext_loc);
897 				h->udfs.ricb_len =
898 					SWAP_32(fsd->fsd_root_icb.lad_ext_len);
899 			}
900 			if (SWAP_32(fsd->fsd_next.lad_ext_len) != 0) {
901 				fsd_prn = SWAP_16(fsd->fsd_next.lad_ext_prn);
902 				fsd_loc = SWAP_32(fsd->fsd_next.lad_ext_loc);
903 				fsd_len = SWAP_32(fsd->fsd_next.lad_ext_len);
904 				goto begin;
905 			}
906 			break;
907 		case UD_TERM_DESC :
908 
909 			/*
910 			 * Success fully completed
911 			 */
912 			goto end;
913 		default :
914 			/*
915 			 * If you donot undetstand any tag just skip
916 			 * it. This is not a fatal error
917 			 */
918 			break;
919 		}
920 	}
921 
922 end:
923 	free(addr);
924 	if (h->udfs.fsd_len == 0) {
925 		return (1);
926 	}
927 	return (0);
928 }
929 
930 int32_t
931 ud_get_num_blks(ud_handle_t h, uint32_t *blkno)
932 {
933 	struct vtoc vtoc;
934 	struct dk_cinfo dki_info;
935 	int32_t error;
936 
937 	/*
938 	 * Get VTOC from driver
939 	 */
940 	if ((error = ioctl(h->fd, DKIOCGVTOC, (intptr_t)&vtoc)) != 0) {
941 		return (error);
942 	}
943 
944 	/*
945 	 * Verify if is proper
946 	 */
947 	if (vtoc.v_sanity != VTOC_SANE) {
948 		return (EINVAL);
949 	}
950 
951 	/*
952 	 * Get dk_cinfo from driver
953 	 */
954 	if ((error = ioctl(h->fd, DKIOCINFO, (intptr_t)&dki_info)) != 0) {
955 		return (error);
956 	}
957 
958 	if (dki_info.dki_partition >= V_NUMPAR) {
959 		return (EINVAL);
960 	}
961 
962 	/*
963 	 * Return the size of the partition
964 	 */
965 	*blkno = vtoc.v_part[dki_info.dki_partition].p_size;
966 
967 	return (0);
968 }
969 
970 uint32_t
971 ud_xlate_to_daddr(ud_handle_t h, uint16_t prn, uint32_t blkno)
972 {
973 	int32_t i;
974 	struct ud_map *m;
975 	struct ud_part *p;
976 
977 
978 	if (prn < h->n_maps) {
979 		m = &h->maps[prn];
980 		for (i = 0; i < h->n_parts; i++) {
981 			p = &h->part[i];
982 			if (m->udm_pn == p->udp_number) {
983 				return (p->udp_start + blkno);
984 			}
985 		}
986 	}
987 	return (0);
988 }
989 
990 /* ------ END Read and translate the on disk VDS to IN CORE format -------- */
991 
992 int32_t
993 ud_verify_tag(ud_handle_t h, struct tag *tag, uint16_t id,
994 	uint32_t blockno, int32_t do_crc, int32_t print_msg)
995 {
996 	int32_t i;
997 	uint8_t *addr, cksum = 0;
998 	uint16_t crc;
999 
1000 
1001 	/*
1002 	 * Verify Tag Identifier
1003 	 */
1004 	if (tag->tag_id != SWAP_16(id)) {
1005 		if (print_msg != 0) {
1006 			(void) fprintf(stderr,
1007 				gettext("tag does not verify tag %x req %x\n"),
1008 				SWAP_16(tag->tag_id), id);
1009 		}
1010 		return (1);
1011 	}
1012 
1013 	/*
1014 	 * Verify Tag Descriptor Version
1015 	 */
1016 	if (SWAP_16(tag->tag_desc_ver) != h->udfs.ecma_version) {
1017 		if (print_msg != 0) {
1018 			(void) fprintf(stderr,
1019 				gettext("tag version does not match with "
1020 				"NSR descriptor version TAG %x NSR %x\n"),
1021 				SWAP_16(tag->tag_desc_ver),
1022 				h->udfs.ecma_version);
1023 		}
1024 		return (1);
1025 	}
1026 
1027 	/*
1028 	 * Caliculate Tag Checksum
1029 	 */
1030 	addr = (uint8_t *)tag;
1031 	for (i = 0; i <= 15; i++) {
1032 		if (i != 4) {
1033 			cksum += addr[i];
1034 		}
1035 	}
1036 
1037 	/*
1038 	 * Verify Tag Checksum
1039 	 */
1040 	if (cksum != tag->tag_cksum) {
1041 		if (print_msg != 0) {
1042 			(void) fprintf(stderr,
1043 				gettext("Checksum Does not Verify TAG"
1044 				" %x CALC %x\n"), tag->tag_cksum, cksum);
1045 		}
1046 		return (1);
1047 	}
1048 
1049 
1050 	/*
1051 	 * Do we want to do crc
1052 	 */
1053 	if (do_crc) {
1054 		if (tag->tag_crc_len) {
1055 
1056 			/*
1057 			 * Caliculate CRC for the descriptor
1058 			 */
1059 			crc = ud_crc(addr + 0x10, SWAP_16(tag->tag_crc_len));
1060 
1061 			/*
1062 			 * Verify CRC
1063 			 */
1064 			if (crc != SWAP_16(tag->tag_crc)) {
1065 				if (print_msg != 0) {
1066 					(void) fprintf(stderr,
1067 						gettext("CRC Does not verify"
1068 						" TAG %x CALC %x %x\n"),
1069 						SWAP_16(tag->tag_crc),
1070 						crc, addr);
1071 				}
1072 			}
1073 		}
1074 
1075 		/*
1076 		 * Verify Tag Location
1077 		 */
1078 		if (SWAP_32(blockno) != tag->tag_loc) {
1079 			if (print_msg != 0) {
1080 				(void) fprintf(stderr,
1081 					gettext("Tag Location Does not verify"
1082 					" blockno %x tag_blockno %x\n"),
1083 					blockno, SWAP_32(tag->tag_loc));
1084 			}
1085 		}
1086 	}
1087 
1088 	return (0);
1089 }
1090 
1091 
1092 /* ARGSUSED1 */
1093 void
1094 ud_make_tag(ud_handle_t h, struct tag *tag, uint16_t tag_id,
1095 	uint32_t blkno, uint16_t crc_len)
1096 {
1097 	int32_t i;
1098 	uint16_t crc;
1099 	uint8_t *addr, cksum = 0;
1100 
1101 	tag->tag_id = SWAP_16(tag_id);
1102 	tag->tag_desc_ver = SWAP_16(h->udfs.ecma_version);
1103 	tag->tag_cksum = 0;
1104 	tag->tag_res = 0;
1105 
1106 	/*
1107 	 * Calicualte and assign CRC, CRC_LEN
1108 	 */
1109 	addr = (uint8_t *)tag;
1110 	crc = ud_crc(addr + 0x10, crc_len);
1111 	tag->tag_crc = SWAP_16(crc);
1112 	tag->tag_crc_len = SWAP_16(crc_len);
1113 	tag->tag_loc = SWAP_32(blkno);
1114 
1115 	/*
1116 	 * Caliculate Checksum
1117 	 */
1118 	for (i = 0; i <= 15; i++) {
1119 		cksum += addr[i];
1120 	}
1121 
1122 	/*
1123 	 * Assign Checksum
1124 	 */
1125 	tag->tag_cksum = cksum;
1126 }
1127 
1128 /* **************** udf specific subroutines *********************** */
1129 
1130 static uint16_t ud_crc_table[256] = {
1131 	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
1132 	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
1133 	0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
1134 	0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
1135 	0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
1136 	0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
1137 	0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
1138 	0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
1139 	0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
1140 	0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
1141 	0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
1142 	0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
1143 	0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
1144 	0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
1145 	0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
1146 	0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
1147 	0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
1148 	0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
1149 	0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
1150 	0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
1151 	0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
1152 	0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1153 	0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
1154 	0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
1155 	0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
1156 	0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
1157 	0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
1158 	0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
1159 	0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
1160 	0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
1161 	0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
1162 	0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
1163 };
1164 
1165 static uint16_t
1166 ud_crc(uint8_t *addr, int32_t len)
1167 {
1168 	uint16_t crc = 0;
1169 
1170 	while (len-- > 0) {
1171 		crc = ud_crc_table[(crc >> 8 ^ *addr++) & 0xff] ^ (crc<<8);
1172 	}
1173 
1174 	return (crc);
1175 }
1176 
1177 #define	MAXNAMLEN	0x200
1178 
1179 
1180 #define	POUND		0x0023
1181 #define	DOT		0x002E
1182 #define	SLASH		0x002F
1183 #define	UNDERBAR	0x005F
1184 
1185 
1186 static uint16_t htoc[16] = {'0', '1', '2', '3',
1187 	'4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1188 /*
1189  * unicode is the string of 16-bot characters
1190  * length is the number of 16-bit characters
1191  */
1192 static int32_t
1193 UdfTxName(uint16_t *unicode, int32_t count)
1194 {
1195 	int32_t i, j, k, lic, make_crc, dot_loc;
1196 	uint16_t crc;
1197 
1198 	if ((unicode[0] == DOT) &&
1199 		((count == 1) || ((count == 2) && (unicode[1] == DOT)))) {
1200 		crc = DOT;
1201 		if (count == 2) {
1202 			crc += DOT;
1203 		}
1204 		unicode[0] = UNDERBAR;
1205 		unicode[1] = POUND;
1206 		unicode[2] = htoc[(uint16_t)(crc & 0xf000) >> 12];
1207 		unicode[3] = htoc[(uint16_t)(crc & 0xf00) >> 8];
1208 		unicode[4] = htoc[(uint16_t)(crc & 0xf0) >> 4];
1209 		unicode[5] = htoc[crc & 0xf];
1210 		return (6);
1211 	}
1212 	crc = 0;
1213 	j = make_crc = 0;
1214 	lic = dot_loc = -1;
1215 	for (i = 0; i < count; i++) {
1216 		if (make_crc) {
1217 			crc += unicode[i];
1218 		}
1219 		if (unicode[i] == DOT) {
1220 			dot_loc = j;
1221 		}
1222 		if ((unicode[i] == SLASH) ||
1223 			(unicode[i] == 0)) {
1224 			if (make_crc == 0) {
1225 				for (k = 0; k <= i; k++) {
1226 					crc += unicode[k];
1227 				}
1228 				make_crc = 1;
1229 			}
1230 			if (lic != (i - 1)) {
1231 				unicode[j++] = UNDERBAR;
1232 			}
1233 			lic = i;
1234 		} else {
1235 			unicode[j++] = unicode[i];
1236 		}
1237 	}
1238 
1239 	if (make_crc) {
1240 		if (dot_loc != -1) {
1241 			if ((j + 5) > MAXNAMLEN) {
1242 				if ((j - dot_loc + 5) > MAXNAMLEN) {
1243 					j = MAXNAMLEN - 5 + dot_loc;
1244 					for (k = MAXNAMLEN;
1245 						j >= dot_loc; k --, j--) {
1246 						unicode[k] = unicode[j];
1247 					}
1248 					k = 0;
1249 				} else {
1250 					for (k = MAXNAMLEN;
1251 						j >= dot_loc; k--, j--) {
1252 						unicode[k] = unicode[j];
1253 					}
1254 					k -= 4;
1255 				}
1256 				j = MAXNAMLEN;
1257 			} else {
1258 				for (k = j; k >= dot_loc; k--) {
1259 					unicode[k + 5] = unicode[k];
1260 				}
1261 				k = dot_loc;
1262 				j += 5;
1263 			}
1264 		} else {
1265 			if ((j + 5) > MAXNAMLEN) {
1266 				j = MAXNAMLEN;
1267 				k = MAXNAMLEN - 5;
1268 			} else {
1269 				k = j;
1270 				j += 5;
1271 			}
1272 		}
1273 		unicode[k++] = POUND;
1274 		unicode[k++] = htoc[(uint16_t)(crc & 0xf000) >> 12];
1275 		unicode[k++] = htoc[(uint16_t)(crc & 0xf00) >> 8];
1276 		unicode[k++] = htoc[(uint16_t)(crc & 0xf0) >> 4];
1277 		unicode[k++] = htoc[crc & 0xf];
1278 	}
1279 	return (j);
1280 }
1281 
1282 /*
1283  * Assumes the output buffer is large
1284  * enough to hold the uncompressed
1285  * code
1286  */
1287 static int32_t
1288 UncompressUnicode(
1289 	int32_t numberOfBytes,	/* (Input) number of bytes read from media. */
1290 	uint8_t *UDFCompressed,	/* (Input) bytes read from media. */
1291 	uint16_t *unicode)	/* (Output) uncompressed unicode characters. */
1292 {
1293 	int32_t compID;
1294 	int32_t returnValue, unicodeIndex, byteIndex;
1295 
1296 
1297 	/*
1298 	 * Use UDFCompressed to store current byte being read.
1299 	 */
1300 	compID = UDFCompressed[0];
1301 
1302 	/* First check for valid compID. */
1303 	if (compID != 8 && compID != 16) {
1304 		returnValue = -1;
1305 	} else {
1306 		unicodeIndex = 0;
1307 		byteIndex = 1;
1308 
1309 		/* Loop through all the bytes. */
1310 		while (byteIndex < numberOfBytes) {
1311 			if (compID == 16) {
1312 				/*
1313 				 * Move the first byte to the
1314 				 * high bits of the unicode char.
1315 				 */
1316 				unicode[unicodeIndex] =
1317 					UDFCompressed[byteIndex++] << 8;
1318 			} else {
1319 				unicode[unicodeIndex] = 0;
1320 			}
1321 			if (byteIndex < numberOfBytes) {
1322 				/*
1323 				 * Then the next byte to the low bits.
1324 				 */
1325 				unicode[unicodeIndex] |=
1326 					UDFCompressed[byteIndex++];
1327 			}
1328 			unicodeIndex++;
1329 		}
1330 		returnValue = unicodeIndex;
1331 	}
1332 	return (returnValue);
1333 }
1334 
1335 
1336 
1337 
1338 
1339 static int32_t
1340 ud_compressunicode(
1341 	int32_t numberOfChars,	/* (Input) number of unicode characters. */
1342 	int32_t compID,		/* (Input) compression ID to be used. */
1343 	uint16_t *unicode,	/* (Input) unicode characters to compress. */
1344 	uint8_t *UDFCompressed) /* (Output) compressed string, as bytes. */
1345 {
1346 	int32_t byteIndex;
1347 
1348 	if (compID != 8 && compID != 16) {
1349 		/*
1350 		 * Unsupported compression ID !
1351 		 */
1352 		byteIndex = -1;
1353 	} else {
1354 		/*
1355 		 * Place compression code in first byte.
1356 		 */
1357 		UDFCompressed[0] = (uint8_t)compID;
1358 		(void) strncpy((caddr_t)&UDFCompressed[1],
1359 			(caddr_t)unicode, numberOfChars);
1360 		byteIndex = numberOfChars + 1;
1361 	}
1362 	return (byteIndex);
1363 }
1364 
1365 
1366 static int32_t
1367 ud_convert2utf8(uint8_t *ibuf, uint8_t *obuf, int32_t length)
1368 {
1369 	int i, size;
1370 	uint16_t *buf;
1371 
1372 	/* LINTED */
1373 	buf = (uint16_t *)obuf;
1374 
1375 	size = UncompressUnicode(length, ibuf, buf);
1376 
1377 	size = UdfTxName(buf, size);
1378 
1379 	for (i = 0; i < size; i++) {
1380 		obuf[i] = (uint8_t)buf[i];
1381 	}
1382 	obuf[i] = '\0';
1383 
1384 	return (size);
1385 }
1386 
1387 static int32_t
1388 ud_convert2utf16(uint8_t *ibuf, uint8_t *obuf, int32_t length)
1389 {
1390 	int32_t comp_len;
1391 	uint16_t *ptr;
1392 
1393 	/* LINTED */
1394 	ptr = (uint16_t *)ibuf;
1395 	comp_len = ud_compressunicode(length, 8, ptr, obuf);
1396 
1397 	return (comp_len);
1398 }
1399 
1400 /*
1401  * Assumption code set is zero in udfs
1402  */
1403 void
1404 ud_convert2local(int8_t *ibuf, int8_t *obuf, int32_t length)
1405 {
1406 	wchar_t buf4c[128];
1407 	int32_t i, comp, index;
1408 
1409 	/*
1410 	 * Special uncompress code
1411 	 * written to accomodate solaris wchar_t
1412 	 */
1413 	comp = ibuf[0];
1414 	for (i = 0, index = 1; i < length; i++) {
1415 		if (comp == 16) {
1416 			buf4c[i] = ibuf[index++] << 8;
1417 		} else {
1418 			buf4c[i] = 0;
1419 		}
1420 		if (index < length) {
1421 			buf4c[i] |= ibuf[index++];
1422 		}
1423 	}
1424 	(void) wcstombs((char *)obuf, buf4c, 128);
1425 }
1426 
1427 
1428 /* ------------ Routines to print basic structures Part 1 ---------------- */
1429 
1430 
1431 
1432 void
1433 print_charspec(FILE *fout, char *name, struct charspec *cspec)
1434 {
1435 	int i = 0;
1436 
1437 	(void) fprintf(fout,
1438 		"%s : %x - \"", name, cspec->cs_type);
1439 	for (i = 0; i < 63; i++) {
1440 		(void) fprintf(fout,
1441 			"%c", cspec->cs_info[i]);
1442 	}
1443 	(void) fprintf(fout, "\n");
1444 }
1445 
1446 /* ARGSUSED */
1447 void
1448 print_dstring(FILE *fout, char *name, uint16_t cset, char *bufc, uint8_t length)
1449 {
1450 	int8_t bufmb[1024];
1451 
1452 	ud_convert2local(bufc, bufmb, length);
1453 
1454 	(void) fprintf(fout,
1455 		"%s %s\n", name, bufmb);
1456 }
1457 
1458 void
1459 set_dstring(dstring_t *dp, char *cp, int32_t len)
1460 {
1461 	int32_t length;
1462 
1463 	bzero(dp, len);
1464 	length = strlen(cp);
1465 	if (length > len - 1) {
1466 		length = len - 1;
1467 	}
1468 	(void) strncpy(dp, cp, length);
1469 	dp[len - 1] = length;
1470 }
1471 
1472 void
1473 print_tstamp(FILE *fout, char *name, tstamp_t *ts)
1474 {
1475 	(void) fprintf(fout, "%s tz : %d yr : %d mo : %d da : %d "
1476 		"Time : %d : %d : %d : %d : %d : %d\n", name,
1477 		SWAP_16(ts->ts_tzone), SWAP_16(ts->ts_year), ts->ts_month,
1478 		ts->ts_day, ts->ts_hour, ts->ts_min, ts->ts_sec, ts->ts_csec,
1479 		ts->ts_husec, ts->ts_usec);
1480 }
1481 
1482 
1483 
1484 void
1485 make_regid(ud_handle_t h, struct regid *reg, char *id, int32_t type)
1486 {
1487 	reg->reg_flags = 0;
1488 	(void) strncpy(reg->reg_id, id, 23);
1489 
1490 	if (type == REG_DOM_ID) {
1491 		struct dom_id_suffix *dis;
1492 
1493 		/* LINTED */
1494 		dis = (struct dom_id_suffix *)reg->reg_ids;
1495 		dis->dis_udf_revison = SWAP_16(h->udfs.ma_write);
1496 		dis->dis_domain_flags = 0;
1497 
1498 	} else if (type == REG_UDF_ID) {
1499 		struct udf_id_suffix *uis;
1500 
1501 		/* LINTED */
1502 		uis = (struct udf_id_suffix *)reg->reg_ids;
1503 		uis->uis_udf_revision = SWAP_16(h->udfs.ma_write);
1504 		uis->uis_os_class = OS_CLASS_UNIX;
1505 		uis->uis_os_identifier = OS_IDENTIFIER_SOLARIS;
1506 	} else if (type == REG_UDF_II) {
1507 		struct impl_id_suffix *iis;
1508 
1509 		iis = (struct impl_id_suffix *)reg->reg_ids;
1510 		iis->iis_os_class = OS_CLASS_UNIX;
1511 		iis->iis_os_identifier = OS_IDENTIFIER_SOLARIS;
1512 	}
1513 }
1514 
1515 void
1516 print_regid(FILE *fout, char *name, struct regid *reg, int32_t type)
1517 {
1518 	(void) fprintf(fout, "%s : 0x%x : \"%s\" :",
1519 		name, reg->reg_flags, reg->reg_id);
1520 
1521 	if (type == REG_DOM_ID) {
1522 		struct dom_id_suffix *dis;
1523 
1524 		/* LINTED */
1525 		dis = (struct dom_id_suffix *)reg->reg_ids;
1526 		(void) fprintf(fout, " 0x%x : %s : %s\n",
1527 			SWAP_16(dis->dis_udf_revison),
1528 			(dis->dis_domain_flags & PROTECT_SOFT_WRITE) ?
1529 				"HW Protect" : "No HW Write Protect",
1530 			(dis->dis_domain_flags & PROTECT_HARD_WRITE) ?
1531 				"SW Protect" : "No SW Protect");
1532 	} else if (type == REG_UDF_ID) {
1533 		struct udf_id_suffix *uis;
1534 
1535 		/* LINTED */
1536 		uis = (struct udf_id_suffix *)reg->reg_ids;
1537 		(void) fprintf(fout,
1538 			" 0x%x : OS Class 0x%x : OS Identifier 0x%x\n",
1539 			SWAP_16(uis->uis_udf_revision),
1540 			uis->uis_os_class, uis->uis_os_identifier);
1541 	} else {
1542 		struct impl_id_suffix *iis;
1543 
1544 		iis = (struct impl_id_suffix *)reg->reg_ids;
1545 		(void) fprintf(fout,
1546 			" OS Class 0x%x : OS Identifier 0x%x\n",
1547 			iis->iis_os_class, iis->iis_os_identifier);
1548 	}
1549 }
1550 
1551 #ifdef	OLD
1552 void
1553 print_regid(FILE *fout, char *name, struct regid *reg)
1554 {
1555 	(void) fprintf(fout, "%s : 0x%x : \"%s\" :",
1556 		name, reg->reg_flags, reg->reg_id);
1557 
1558 	if (strncmp(reg->reg_id, "*OSTA UDF Compliant", 19) == 0) {
1559 		(void) fprintf(fout, " 0x%x : %s : %s\n",
1560 			reg->reg_ids[0] | (reg->reg_ids[1] << 8),
1561 			(reg->reg_ids[2] & 1) ?
1562 				"HW Protect" : "No HW Write Protect",
1563 			(reg->reg_ids[2] & 2) ?
1564 				"SW Protect" : "No SW Protect");
1565 	} else if ((strncmp(reg->reg_id, "*UDF Virtual Partition", 22) == 0) ||
1566 		(strncmp(reg->reg_id, "*UDF Sparable Partition", 23) == 0) ||
1567 		(strncmp(reg->reg_id, "*UDF Virtual Alloc Tbl", 22) == 0) ||
1568 		(strncmp(reg->reg_id, "*UDF Sparing Table", 18) == 0)) {
1569 		(void) fprintf(fout,
1570 			" 0x%x : OS Class 0x%x : OS Identifier 0x%x\n",
1571 			reg->reg_ids[0] | (reg->reg_ids[1] << 8),
1572 			reg->reg_ids[2], reg->reg_ids[3]);
1573 	} else {
1574 		(void) fprintf(fout,
1575 			" OS Class 0x%x : OS Identifier 0x%x\n",
1576 			reg->reg_ids[0], reg->reg_ids[1]);
1577 	}
1578 }
1579 #endif
1580 
1581 
1582 /* ------------ Routines to print basic structures Part 2 ---------------- */
1583 /*
1584  * Part 2
1585  * This part is OS specific and is currently
1586  * not supported
1587  */
1588 
1589 /* ------------ Routines to print basic structures Part 3 ---------------- */
1590 
1591 void
1592 print_ext_ad(FILE *fout, char *name, struct extent_ad *ead)
1593 {
1594 	(void) fprintf(fout,
1595 		"%s EAD Len %x Loc %x\n",
1596 		name, SWAP_32(ead->ext_len), SWAP_32(ead->ext_loc));
1597 }
1598 
1599 void
1600 print_tag(FILE *fout, struct tag *tag)
1601 {
1602 	(void) fprintf(fout,
1603 		"tag_id : %x ver : %x cksum : %x "
1604 		"sno : %x crc : %x crc_len : %x loc : %x\n",
1605 		SWAP_16(tag->tag_id), SWAP_16(tag->tag_desc_ver),
1606 		tag->tag_cksum, SWAP_16(tag->tag_sno),
1607 		SWAP_16(tag->tag_crc), SWAP_16(tag->tag_crc_len),
1608 		SWAP_32(tag->tag_loc));
1609 }
1610 
1611 
1612 void
1613 print_pvd(FILE *fout, struct pri_vol_desc *pvd)
1614 {
1615 	(void) fprintf(fout,
1616 		"\n\t\t\tPrimary Volume Descriptor\n");
1617 	print_tag(fout, &pvd->pvd_tag);
1618 	(void) fprintf(fout, "vdsn : %x vdn : %x\n",
1619 		SWAP_32(pvd->pvd_vdsn), SWAP_32(pvd->pvd_pvdn));
1620 	print_dstring(fout, "volid : ", pvd->pvd_desc_cs.cs_type,
1621 			pvd->pvd_vol_id, 32);
1622 	(void) fprintf(fout,
1623 		"vsn : %x mvsn : %x il : %x mil :"
1624 		" %x csl : %x mcsl %x\n",
1625 		SWAP_16(pvd->pvd_vsn), SWAP_16(pvd->pvd_mvsn),
1626 		SWAP_16(pvd->pvd_il), SWAP_16(pvd->pvd_mil),
1627 		SWAP_32(pvd->pvd_csl), SWAP_32(pvd->pvd_mcsl));
1628 	print_dstring(fout, "vsid :", pvd->pvd_desc_cs.cs_type,
1629 			pvd->pvd_vsi, 128);
1630 	print_charspec(fout, "desc_cs", &pvd->pvd_desc_cs);
1631 	print_charspec(fout, "exp_cs", &pvd->pvd_exp_cs);
1632 	print_ext_ad(fout, "val ", &pvd->pvd_vol_abs);
1633 	print_ext_ad(fout, "vcnl ", &pvd->pvd_vcn);
1634 	print_regid(fout, "ai", &pvd->pvd_appl_id, REG_UDF_II);
1635 	print_regid(fout, "ii", &pvd->pvd_ii, REG_UDF_II);
1636 	(void) fprintf(fout, "pvdsl : %x flags : %x\n",
1637 		SWAP_32(pvd->pvd_pvdsl),
1638 		SWAP_16(pvd->pvd_flags));
1639 }
1640 
1641 void
1642 print_avd(FILE *fout, struct anch_vol_desc_ptr *avdp)
1643 {
1644 	(void) fprintf(fout,
1645 		"\n\t\t\tAnchor Volume Descriptor\n");
1646 	print_tag(fout, &avdp->avd_tag);
1647 	print_ext_ad(fout, "Main Volume Descriptor Sequence : ",
1648 			&avdp->avd_main_vdse);
1649 	print_ext_ad(fout, "Reserve Volume Descriptor Sequence : ",
1650 			&avdp->avd_res_vdse);
1651 }
1652 
1653 void
1654 print_vdp(FILE *fout, struct vol_desc_ptr *vdp)
1655 {
1656 	(void) fprintf(fout,
1657 		"\n\t\t\tVolume Descriptor Pointer\n");
1658 	print_tag(fout, &vdp->vdp_tag);
1659 	(void) fprintf(fout, "vdsn : %x ",
1660 		SWAP_32(vdp->vdp_vdsn));
1661 	print_ext_ad(fout, "vdse ", &vdp->vdp_nvdse);
1662 }
1663 
1664 void
1665 print_iuvd(FILE *fout, struct iuvd_desc *iuvd)
1666 {
1667 	(void) fprintf(fout,
1668 		"\n\t\t\tImplementation Use Volume Descriptor\n");
1669 	print_tag(fout, &iuvd->iuvd_tag);
1670 	(void) fprintf(fout,
1671 		"vdsn : %x ", SWAP_32(iuvd->iuvd_vdsn));
1672 	print_regid(fout, "Impl Id : ", &iuvd->iuvd_ii, REG_UDF_ID);
1673 	print_charspec(fout, "cset ", &iuvd->iuvd_cset);
1674 	print_dstring(fout, "lvi : ", iuvd->iuvd_cset.cs_type,
1675 			iuvd->iuvd_lvi, 128);
1676 	print_dstring(fout, "ifo1 : ", iuvd->iuvd_cset.cs_type,
1677 			iuvd->iuvd_ifo1, 36);
1678 	print_dstring(fout, "ifo2 : ", iuvd->iuvd_cset.cs_type,
1679 			iuvd->iuvd_ifo2, 36);
1680 	print_dstring(fout, "ifo3 : ", iuvd->iuvd_cset.cs_type,
1681 			iuvd->iuvd_ifo3, 36);
1682 
1683 	print_regid(fout, "iid ", &iuvd->iuvd_iid, REG_UDF_II);
1684 }
1685 
1686 void
1687 print_part(FILE *fout, struct part_desc *pd)
1688 {
1689 	(void) fprintf(fout,
1690 		"\n\t\t\tPartition Descriptor\n");
1691 	print_tag(fout, &pd->pd_tag);
1692 	(void) fprintf(fout,
1693 		"vdsn : %x flags : %x num : %x ",
1694 		SWAP_32(pd->pd_vdsn),
1695 		SWAP_16(pd->pd_pflags),
1696 		SWAP_16(pd->pd_pnum));
1697 	print_regid(fout, "contents ", &pd->pd_pcontents, REG_UDF_II);
1698 	/* LINTED */
1699 	print_phdr(fout, (struct phdr_desc *)(&pd->pd_pc_use));
1700 	(void) fprintf(fout,
1701 		"acc : %x start : %x length : %x ",
1702 		SWAP_32(pd->pd_acc_type),
1703 		SWAP_32(pd->pd_part_start),
1704 		SWAP_32(pd->pd_part_length));
1705 	print_regid(fout, "Impl Id : ", &pd->pd_ii, REG_UDF_II);
1706 }
1707 
1708 void
1709 print_lvd(FILE *fout, struct log_vol_desc *lvd)
1710 {
1711 	(void) fprintf(fout,
1712 		"\n\t\t\tLogical Volume Descriptor\n");
1713 	print_tag(fout, &lvd->lvd_tag);
1714 	(void) fprintf(fout,
1715 		"vdsn : %x ", SWAP_32(lvd->lvd_vdsn));
1716 	print_charspec(fout, "Desc Char Set ", &lvd->lvd_desc_cs);
1717 	print_dstring(fout, "lvid : ", lvd->lvd_desc_cs.cs_type,
1718 			lvd->lvd_lvid, 28);
1719 	(void) fprintf(fout,
1720 		"lbsize : %x ",
1721 		SWAP_32(lvd->lvd_log_bsize));
1722 	print_regid(fout, "Dom Id", &lvd->lvd_dom_id, REG_DOM_ID);
1723 	print_long_ad(fout, "lvcu", &lvd->lvd_lvcu);
1724 	(void) fprintf(fout,
1725 		"mtlen : %x nmaps : %x ",
1726 		SWAP_32(lvd->lvd_mtbl_len),
1727 		SWAP_32(lvd->lvd_num_pmaps));
1728 	print_regid(fout, "Impl Id : ", &lvd->lvd_ii, REG_UDF_II);
1729 	print_ext_ad(fout, "Int Seq", &lvd->lvd_int_seq_ext);
1730 	print_pmaps(fout, lvd->lvd_pmaps, SWAP_32(lvd->lvd_num_pmaps));
1731 }
1732 
1733 void
1734 print_usd(FILE *fout, struct unall_spc_desc *ua)
1735 {
1736 	int32_t i, count;
1737 
1738 	(void) fprintf(fout,
1739 		"\n\t\t\tUnallocated Space Descriptor\n");
1740 	print_tag(fout, &ua->ua_tag);
1741 	count = SWAP_32(ua->ua_nad);
1742 	(void) fprintf(fout,
1743 		"vdsn : %x nad : %x\n",
1744 		SWAP_32(ua->ua_vdsn), count);
1745 	for (i = 0; i < count; i++) {
1746 		(void) fprintf(fout,
1747 			"loc : %x len : %x\n",
1748 			SWAP_32(ua->ua_al_dsc[i * 2]),
1749 			SWAP_32(ua->ua_al_dsc[i * 2 + 1]));
1750 	}
1751 }
1752 
1753 void
1754 print_lvid(FILE *fout, struct log_vol_int_desc *lvid)
1755 {
1756 	int32_t i, count;
1757 	caddr_t addr;
1758 	struct lvid_iu *liu;
1759 
1760 	(void) fprintf(fout,
1761 		"\n\t\t\tLogical Volume Integrity Descriptor\n");
1762 	print_tag(fout, &lvid->lvid_tag);
1763 	print_tstamp(fout, "Rec TM ", &lvid->lvid_tstamp);
1764 	if (SWAP_32(lvid->lvid_int_type) == 0) {
1765 		(void) fprintf(fout,
1766 			"int_typ : Open\n");
1767 	} else if (SWAP_32(lvid->lvid_int_type) == 1) {
1768 		(void) fprintf(fout, "int_typ : Closed\n");
1769 	} else {
1770 		(void) fprintf(fout, "int_typ : Unknown\n");
1771 	}
1772 	print_ext_ad(fout, "Nie ", &lvid->lvid_nie);
1773 	count = SWAP_32(lvid->lvid_npart);
1774 	(void) fprintf(fout,
1775 		"Uniq : %llx npart : %x liu : %x\n",
1776 		SWAP_64(lvid->lvid_lvcu.lvhd_uniqid),
1777 		count, SWAP_32(lvid->lvid_liu));
1778 	for (i = 0; i < count; i++) {
1779 		(void) fprintf(fout,
1780 			"Part : %x Free : %x Size : %x\n",
1781 			i, SWAP_32(lvid->lvid_fst[i]),
1782 			SWAP_32(lvid->lvid_fst[count + i]));
1783 	}
1784 
1785 	addr = (caddr_t)lvid->lvid_fst;
1786 	/* LINTED */
1787 	liu = (struct lvid_iu *)(addr + 2 * count * 4);
1788 	print_regid(fout, "Impl Id :", &liu->lvidiu_regid, REG_UDF_II);
1789 	(void) fprintf(fout,
1790 		"nfiles : %x ndirs : %x miread : %x"
1791 		" miwrite : %x mawrite : %x\n",
1792 		SWAP_32(liu->lvidiu_nfiles), SWAP_32(liu->lvidiu_ndirs),
1793 		SWAP_16(liu->lvidiu_mread), SWAP_16(liu->lvidiu_mwrite),
1794 		SWAP_16(liu->lvidiu_maxwr));
1795 }
1796 
1797 
1798 /* ------------ Routines to print basic structures Part 4 ---------------- */
1799 
1800 void
1801 print_fsd(FILE *fout, ud_handle_t h, struct file_set_desc *fsd)
1802 {
1803 	(void) fprintf(fout,
1804 		"\n\t\t\tFile Set Descriptor\n");
1805 
1806 	print_tag(fout, &fsd->fsd_tag);
1807 	print_tstamp(fout, "Rec TM ", &fsd->fsd_time);
1808 	(void) fprintf(fout,
1809 		"ilvl : %x milvl : %x csl : %x"
1810 		" mcsl : %x fsn : %x fsdn : %x\n",
1811 		SWAP_16(fsd->fsd_ilevel), SWAP_16(fsd->fsd_mi_level),
1812 		SWAP_32(fsd->fsd_cs_list), SWAP_32(fsd->fsd_mcs_list),
1813 		SWAP_32(fsd->fsd_fs_no), SWAP_32(fsd->fsd_fsd_no));
1814 	print_charspec(fout, "ID CS ", &fsd->fsd_lvidcs);
1815 	print_dstring(fout, "lvi : ", fsd->fsd_lvidcs.cs_type,
1816 			fsd->fsd_lvid, 128);
1817 	print_charspec(fout, "ID CS ", &fsd->fsd_fscs);
1818 	print_dstring(fout, "fsi : ", fsd->fsd_lvidcs.cs_type,
1819 			fsd->fsd_fsi, 32);
1820 	print_dstring(fout, "cfi : ", fsd->fsd_lvidcs.cs_type,
1821 			fsd->fsd_cfi, 32);
1822 	print_dstring(fout, "afi : ", fsd->fsd_lvidcs.cs_type,
1823 			fsd->fsd_afi, 32);
1824 	print_long_ad(fout, "Ricb ", &fsd->fsd_root_icb);
1825 	print_regid(fout, "DI ", &fsd->fsd_did, REG_DOM_ID);
1826 	print_long_ad(fout, "Next Fsd ", &fsd->fsd_next);
1827 	if (h->udfs.ecma_version == UD_ECMA_VER3) {
1828 		print_long_ad(fout, "System Stream Directory ICB ",
1829 				&fsd->fsd_next);
1830 	}
1831 }
1832 
1833 void
1834 print_phdr(FILE *fout, struct phdr_desc *ph)
1835 {
1836 	print_short_ad(fout, "ust ", &ph->phdr_ust);
1837 	print_short_ad(fout, "usb ", &ph->phdr_usb);
1838 	print_short_ad(fout, "int ", &ph->phdr_it);
1839 	print_short_ad(fout, "fst ", &ph->phdr_fst);
1840 	print_short_ad(fout, "fsh ", &ph->phdr_fsb);
1841 }
1842 
1843 void
1844 print_fid(FILE *fout, struct file_id *fid)
1845 {
1846 	int32_t i;
1847 	uint8_t *addr;
1848 
1849 	(void) fprintf(fout,
1850 		"File Identifier Descriptor\n");
1851 	print_tag(fout, &fid->fid_tag);
1852 	(void) fprintf(fout, "fvn : %x fc : %x length : %x ",
1853 		fid->fid_ver, fid->fid_flags, fid->fid_idlen);
1854 	print_long_ad(fout, "ICB", &fid->fid_icb);
1855 	addr = &fid->fid_spec[SWAP_16(fid->fid_iulen)];
1856 	(void) fprintf(fout, "iulen : %x comp : %x name : ",
1857 		SWAP_16(fid->fid_iulen), *addr);
1858 	addr++;
1859 	for (i = 0; i < fid->fid_idlen; i++) {
1860 		(void) fprintf(fout, "%c", *addr++);
1861 	}
1862 	(void) fprintf(fout, "\n");
1863 }
1864 
1865 void
1866 print_aed(FILE *fout, struct alloc_ext_desc *aed)
1867 {
1868 	(void) fprintf(fout,
1869 		"Allocation Extent Descriptor\n");
1870 	print_tag(fout, &aed->aed_tag);
1871 	(void) fprintf(fout, "prev ael loc : %x laed : %x\n",
1872 		SWAP_32(aed->aed_rev_ael), SWAP_32(aed->aed_len_aed));
1873 }
1874 
1875 static char *ftype[] = {
1876 	"NON",  "USE",  "PIE",  "IE",
1877 	"DIR",  "REG",  "BDEV", "CDEV",
1878 	"EATT", "FIFO", "SOCK", "TERM",
1879 	"SYML", "SDIR"
1880 };
1881 
1882 void
1883 print_icb_tag(FILE *fout, struct icb_tag *itag)
1884 {
1885 	(void) fprintf(fout,
1886 		"prnde : %x strat : %x param : %x max_ent %x\n",
1887 		SWAP_32(itag->itag_prnde), SWAP_16(itag->itag_strategy),
1888 		SWAP_16(itag->itag_param), SWAP_16(itag->itag_max_ent));
1889 	(void) fprintf(fout,
1890 		"ftype : %s prn : %x loc : %x flags : %x\n",
1891 		(itag->itag_ftype >= 14) ? ftype[0] : ftype[itag->itag_ftype],
1892 		SWAP_16(itag->itag_lb_prn),
1893 		SWAP_32(itag->itag_lb_loc), SWAP_16(itag->itag_flags));
1894 }
1895 
1896 
1897 void
1898 print_ie(FILE *fout, struct indirect_entry *ie)
1899 {
1900 	(void) fprintf(fout,
1901 		"Indirect Entry\n");
1902 	print_tag(fout, &ie->ie_tag);
1903 	print_icb_tag(fout, &ie->ie_icb_tag);
1904 	print_long_ad(fout, "ICB", &ie->ie_indirecticb);
1905 }
1906 
1907 void
1908 print_td(FILE *fout, struct term_desc *td)
1909 {
1910 	(void) fprintf(fout,
1911 		"Terminating Descriptor\n");
1912 	print_tag(fout, &td->td_tag);
1913 }
1914 
1915 void
1916 print_fe(FILE *fout, struct file_entry *fe)
1917 {
1918 	(void) fprintf(fout,
1919 		"File Entry\n");
1920 	print_tag(fout, &fe->fe_tag);
1921 	print_icb_tag(fout, &fe->fe_icb_tag);
1922 	(void) fprintf(fout,
1923 		"uid : %x gid : %x perms : %x nlnk : %x\n",
1924 		SWAP_32(fe->fe_uid), SWAP_32(fe->fe_gid),
1925 		SWAP_32(fe->fe_perms), SWAP_16(fe->fe_lcount));
1926 	(void) fprintf(fout,
1927 		"rec_for : %x rec_dis : %x rec_len : %x "
1928 		"sz : %llx blks : %llx\n",
1929 		fe->fe_rec_for, fe->fe_rec_dis, SWAP_32(fe->fe_rec_len),
1930 		SWAP_64(fe->fe_info_len), SWAP_64(fe->fe_lbr));
1931 	print_tstamp(fout, "ctime ", &fe->fe_acc_time);
1932 	print_tstamp(fout, "mtime ", &fe->fe_mod_time);
1933 	print_tstamp(fout, "atime ", &fe->fe_attr_time);
1934 	(void) fprintf(fout,
1935 		"ckpoint : %x ", SWAP_32(fe->fe_ckpoint));
1936 	print_long_ad(fout, "ICB", &fe->fe_ea_icb);
1937 	print_regid(fout, "impl", &fe->fe_impl_id, REG_UDF_II);
1938 	(void) fprintf(fout,
1939 		"uniq_id : %llx len_ear : %x len_adesc %x\n",
1940 		SWAP_64(fe->fe_uniq_id), SWAP_32(fe->fe_len_ear),
1941 		SWAP_32(fe->fe_len_adesc));
1942 }
1943 
1944 void
1945 print_pmaps(FILE *fout, uint8_t *addr, int32_t count)
1946 {
1947 	struct pmap_hdr *hdr;
1948 	struct pmap_typ1 *map1;
1949 	struct pmap_typ2 *map2;
1950 
1951 	while (count--) {
1952 		hdr = (struct pmap_hdr *)addr;
1953 		switch (hdr->maph_type) {
1954 		case 1 :
1955 			/* LINTED */
1956 			map1 = (struct pmap_typ1 *)hdr;
1957 			(void) fprintf(fout, "Map type 1 ");
1958 			(void) fprintf(fout, "VSN %x prn %x\n",
1959 					SWAP_16(map1->map1_vsn),
1960 					SWAP_16(map1->map1_pn));
1961 			break;
1962 		case 2 :
1963 			/* LINTED */
1964 			map2 = (struct pmap_typ2 *)hdr;
1965 			(void) fprintf(fout, "Map type 2 ");
1966 			(void) fprintf(fout, "VSN %x prn %x\n",
1967 					SWAP_16(map2->map2_vsn),
1968 					SWAP_16(map2->map2_pn));
1969 			print_regid(fout, "Partition Type Identifier",
1970 					&map2->map2_pti, REG_UDF_ID);
1971 			break;
1972 		default :
1973 			(void) fprintf(fout, "unknown map type\n");
1974 		}
1975 		addr += hdr->maph_length;
1976 	}
1977 }
1978 
1979 
1980 
1981 void
1982 print_short_ad(FILE *fout, char *name, struct short_ad *sad)
1983 {
1984 	(void) fprintf(fout,
1985 		"%s loc : %x len : %x\n", name,
1986 		SWAP_32(sad->sad_ext_loc), SWAP_32(sad->sad_ext_len));
1987 }
1988 
1989 void
1990 print_long_ad(FILE *fout, char *name, struct long_ad *lad)
1991 {
1992 	(void) fprintf(fout,
1993 		"%s prn : %x loc : %x len : %x\n", name,
1994 		SWAP_16(lad->lad_ext_prn), SWAP_32(lad->lad_ext_loc),
1995 		SWAP_32(lad->lad_ext_len));
1996 }
1997