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