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
47extern char *getfullrawname(char *);
48
49static int32_t ud_get_ecma_ver(ud_handle_t, uint32_t);
50static int32_t ud_get_fs_bsize(ud_handle_t, uint32_t, uint32_t *);
51static int32_t ud_parse_fill_vds(ud_handle_t, struct vds *, uint32_t, uint32_t);
52static int32_t	ud_read_and_translate_lvd(ud_handle_t, uint32_t, uint32_t);
53static int32_t ud_get_latest_lvid(ud_handle_t, uint32_t, uint32_t);
54static int32_t	ud_get_latest_fsd(ud_handle_t, uint16_t, uint32_t, uint32_t);
55
56static uint16_t ud_crc(uint8_t *, int32_t);
57static int32_t UdfTxName(uint16_t *, int32_t);
58static int32_t UncompressUnicode(int32_t, uint8_t *, uint16_t *);
59static int32_t ud_compressunicode(int32_t, int32_t, uint16_t *, uint8_t *);
60static int32_t ud_convert2utf8(uint8_t *, uint8_t *, int32_t);
61static int32_t ud_convert2utf16(uint8_t *, uint8_t *, int32_t);
62
63
64int
65ud_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
77void
78ud_fini(ud_handle_t h)
79{
80	free(h);
81}
82
83/* ARGSUSED */
84int32_t
85ud_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 */
140void
141ud_close_dev(ud_handle_t h)
142{
143	/*
144	 * Too simple Just close it
145	 */
146	(void) close(h->fd);
147}
148
149int32_t
150ud_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
168int32_t
169ud_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
189int32_t
190ud_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
275static int32_t
276ud_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
341end:
342	/*
343	 * Cleanup
344	 */
345	free(buf);
346	return (ecma_ver);
347}
348
349static uint32_t last_block_index[] = {0, 0, 256, 2, 2 + 256,
350		150, 150 + 256, 152, 152 + 256};
351
352static int32_t
353ud_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
441end:
442	if (bsize > MAXBSIZE) {
443		bsize = 0;
444		*avd_loc = 0;
445	}
446	free(buf);
447	return (bsize);
448}
449
450static int32_t
451ud_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
464begin:
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
626end:
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
637static int32_t
638ud_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
771static int32_t
772ud_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
780begin:
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	}
844end:
845	free(addr);
846	if (h->udfs.lvid_len == 0) {
847		return (1);
848	}
849	return (0);
850}
851
852static int32_t
853ud_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
864begin:
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
933end:
934	free(addr);
935	if (h->udfs.fsd_len == 0) {
936		return (1);
937	}
938	return (0);
939}
940
941int32_t
942ud_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
981uint32_t
982ud_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
1003int32_t
1004ud_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 */
1104void
1105ud_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
1141static 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
1176static uint16_t
1177ud_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
1197static 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 */
1203static int32_t
1204UdfTxName(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 */
1298static int32_t
1299UncompressUnicode(
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
1350static int32_t
1351ud_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
1377static int32_t
1378ud_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
1398static int32_t
1399ud_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 */
1414void
1415ud_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
1443void
1444print_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 */
1458void
1459print_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
1469void
1470set_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
1483void
1484print_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
1495void
1496make_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
1526void
1527print_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
1563void
1564print_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
1602void
1603print_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
1610void
1611print_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
1623void
1624print_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
1652void
1653print_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
1664void
1665print_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
1675void
1676print_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
1697void
1698print_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
1719void
1720print_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
1744void
1745print_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
1764void
1765print_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
1811void
1812print_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
1844void
1845print_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
1854void
1855print_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
1876void
1877print_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
1886static char *ftype[] = {
1887	"NON",  "USE",  "PIE",  "IE",
1888	"DIR",  "REG",  "BDEV", "CDEV",
1889	"EATT", "FIFO", "SOCK", "TERM",
1890	"SYML", "SDIR"
1891};
1892
1893void
1894print_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
1908void
1909print_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
1918void
1919print_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
1926void
1927print_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
1955void
1956print_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
1992void
1993print_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
2000void
2001print_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