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