1 /* $NetBSD: udf_subr.c,v 1.15 2006/09/05 22:30:52 reinoud Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Reinoud Zandijk 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the 18 * NetBSD Project. See http://www.NetBSD.org/ for 19 * information about NetBSD. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 */ 35 36 37 #include <sys/cdefs.h> 38 #ifndef lint 39 __RCSID("$NetBSD: udf_subr.c,v 1.15 2006/09/05 22:30:52 reinoud Exp $"); 40 #endif /* not lint */ 41 42 43 #if defined(_KERNEL_OPT) 44 #include "opt_quota.h" 45 #include "opt_compat_netbsd.h" 46 #endif 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/sysctl.h> 51 #include <sys/namei.h> 52 #include <sys/proc.h> 53 #include <sys/kernel.h> 54 #include <sys/vnode.h> 55 #include <miscfs/genfs/genfs_node.h> 56 #include <sys/mount.h> 57 #include <sys/buf.h> 58 #include <sys/file.h> 59 #include <sys/device.h> 60 #include <sys/disklabel.h> 61 #include <sys/ioctl.h> 62 #include <sys/malloc.h> 63 #include <sys/dirent.h> 64 #include <sys/stat.h> 65 #include <sys/conf.h> 66 #include <sys/kauth.h> 67 68 #include <fs/udf/ecma167-udf.h> 69 #include <fs/udf/udf_mount.h> 70 71 #include "udf.h" 72 #include "udf_subr.h" 73 #include "udf_bswap.h" 74 75 76 #define VTOI(vnode) ((struct udf_node *) vnode->v_data) 77 78 79 /* predefines */ 80 81 82 #if 0 83 { 84 int i, j, dlen; 85 uint8_t *blob; 86 87 blob = (uint8_t *) fid; 88 dlen = file_size - (*offset); 89 90 printf("blob = %p\n", blob); 91 printf("dump of %d bytes\n", dlen); 92 93 for (i = 0; i < dlen; i+ = 16) { 94 printf("%04x ", i); 95 for (j = 0; j < 16; j++) { 96 if (i+j < dlen) { 97 printf("%02x ", blob[i+j]); 98 } else { 99 printf(" "); 100 } 101 } 102 for (j = 0; j < 16; j++) { 103 if (i+j < dlen) { 104 if (blob[i+j]>32 && blob[i+j]! = 127) { 105 printf("%c", blob[i+j]); 106 } else { 107 printf("."); 108 } 109 } 110 } 111 printf("\n"); 112 } 113 printf("\n"); 114 } 115 Debugger(); 116 #endif 117 118 119 /* --------------------------------------------------------------------- */ 120 121 /* STUB */ 122 123 static int 124 udf_bread(struct udf_mount *ump, uint32_t sector, struct buf **bpp) 125 { 126 int sector_size = ump->discinfo.sector_size; 127 int blks = sector_size / DEV_BSIZE; 128 129 /* NOTE bread() checks if block is in cache or not */ 130 return bread(ump->devvp, sector*blks, sector_size, NOCRED, bpp); 131 } 132 133 134 /* --------------------------------------------------------------------- */ 135 136 /* 137 * Check if the blob starts with a good UDF tag. Tags are protected by a 138 * checksum over the reader except one byte at position 4 that is the checksum 139 * itself. 140 */ 141 142 int 143 udf_check_tag(void *blob) 144 { 145 struct desc_tag *tag = blob; 146 uint8_t *pos, sum, cnt; 147 148 /* check TAG header checksum */ 149 pos = (uint8_t *) tag; 150 sum = 0; 151 152 for(cnt = 0; cnt < 16; cnt++) { 153 if (cnt != 4) 154 sum += *pos; 155 pos++; 156 } 157 if (sum != tag->cksum) { 158 /* bad tag header checksum; this is not a valid tag */ 159 return EINVAL; 160 } 161 162 return 0; 163 } 164 165 /* --------------------------------------------------------------------- */ 166 167 /* 168 * check tag payload will check descriptor CRC as specified. 169 * If the descriptor is too short, it will return EIO otherwise EINVAL. 170 */ 171 172 int 173 udf_check_tag_payload(void *blob, uint32_t max_length) 174 { 175 struct desc_tag *tag = blob; 176 uint16_t crc, crc_len; 177 178 crc_len = udf_rw16(tag->desc_crc_len); 179 180 /* check payload CRC if applicable */ 181 if (crc_len == 0) 182 return 0; 183 184 if (crc_len > max_length) 185 return EIO; 186 187 crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH, crc_len); 188 if (crc != udf_rw16(tag->desc_crc)) { 189 /* bad payload CRC; this is a broken tag */ 190 return EINVAL; 191 } 192 193 return 0; 194 } 195 196 /* --------------------------------------------------------------------- */ 197 198 int 199 udf_validate_tag_sum(void *blob) 200 { 201 struct desc_tag *tag = blob; 202 uint8_t *pos, sum, cnt; 203 204 /* calculate TAG header checksum */ 205 pos = (uint8_t *) tag; 206 sum = 0; 207 208 for(cnt = 0; cnt < 16; cnt++) { 209 if (cnt != 4) sum += *pos; 210 pos++; 211 } 212 tag->cksum = sum; /* 8 bit */ 213 214 return 0; 215 } 216 217 /* --------------------------------------------------------------------- */ 218 219 /* assumes sector number of descriptor to be saved already present */ 220 221 int 222 udf_validate_tag_and_crc_sums(void *blob) 223 { 224 struct desc_tag *tag = blob; 225 uint8_t *btag = (uint8_t *) tag; 226 uint16_t crc, crc_len; 227 228 crc_len = udf_rw16(tag->desc_crc_len); 229 230 /* check payload CRC if applicable */ 231 if (crc_len > 0) { 232 crc = udf_cksum(btag + UDF_DESC_TAG_LENGTH, crc_len); 233 tag->desc_crc = udf_rw16(crc); 234 } 235 236 /* calculate TAG header checksum */ 237 return udf_validate_tag_sum(blob); 238 } 239 240 /* --------------------------------------------------------------------- */ 241 242 /* 243 * XXX note the different semantics from udfclient: for FIDs it still rounds 244 * up to sectors. Use udf_fidsize() for a correct length. 245 */ 246 247 int 248 udf_tagsize(union dscrptr *dscr, uint32_t udf_sector_size) 249 { 250 uint32_t size, tag_id, num_secs, elmsz; 251 252 tag_id = udf_rw16(dscr->tag.id); 253 254 switch (tag_id) { 255 case TAGID_LOGVOL : 256 size = sizeof(struct logvol_desc) - 1; 257 size += udf_rw32(dscr->lvd.mt_l); 258 break; 259 case TAGID_UNALLOC_SPACE : 260 elmsz = sizeof(struct extent_ad); 261 size = sizeof(struct unalloc_sp_desc) - elmsz; 262 size += udf_rw32(dscr->usd.alloc_desc_num) * elmsz; 263 break; 264 case TAGID_FID : 265 size = UDF_FID_SIZE + dscr->fid.l_fi + udf_rw16(dscr->fid.l_iu); 266 size = (size + 3) & ~3; 267 break; 268 case TAGID_LOGVOL_INTEGRITY : 269 size = sizeof(struct logvol_int_desc) - sizeof(uint32_t); 270 size += udf_rw32(dscr->lvid.l_iu); 271 size += (2 * udf_rw32(dscr->lvid.num_part) * sizeof(uint32_t)); 272 break; 273 case TAGID_SPACE_BITMAP : 274 size = sizeof(struct space_bitmap_desc) - 1; 275 size += udf_rw32(dscr->sbd.num_bytes); 276 break; 277 case TAGID_SPARING_TABLE : 278 elmsz = sizeof(struct spare_map_entry); 279 size = sizeof(struct udf_sparing_table) - elmsz; 280 size += udf_rw16(dscr->spt.rt_l) * elmsz; 281 break; 282 case TAGID_FENTRY : 283 size = sizeof(struct file_entry); 284 size += udf_rw32(dscr->fe.l_ea) + udf_rw32(dscr->fe.l_ad)-1; 285 break; 286 case TAGID_EXTFENTRY : 287 size = sizeof(struct extfile_entry); 288 size += udf_rw32(dscr->efe.l_ea) + udf_rw32(dscr->efe.l_ad)-1; 289 break; 290 case TAGID_FSD : 291 size = sizeof(struct fileset_desc); 292 break; 293 default : 294 size = sizeof(union dscrptr); 295 break; 296 } 297 298 if ((size == 0) || (udf_sector_size == 0)) return 0; 299 300 /* round up in sectors */ 301 num_secs = (size + udf_sector_size -1) / udf_sector_size; 302 return num_secs * udf_sector_size; 303 } 304 305 306 static int 307 udf_fidsize(struct fileid_desc *fid, uint32_t udf_sector_size) 308 { 309 uint32_t size; 310 311 if (udf_rw16(fid->tag.id) != TAGID_FID) 312 panic("got udf_fidsize on non FID\n"); 313 314 size = UDF_FID_SIZE + fid->l_fi + udf_rw16(fid->l_iu); 315 size = (size + 3) & ~3; 316 317 return size; 318 } 319 320 /* --------------------------------------------------------------------- */ 321 322 /* 323 * Problem with read_descriptor are long descriptors spanning more than one 324 * sector. Luckily long descriptors can't be in `logical space'. 325 * 326 * Size of allocated piece is returned in multiple of sector size due to 327 * udf_calc_udf_malloc_size(). 328 */ 329 330 int 331 udf_read_descriptor(struct udf_mount *ump, uint32_t sector, 332 struct malloc_type *mtype, union dscrptr **dstp) 333 { 334 union dscrptr *src, *dst; 335 struct buf *bp; 336 uint8_t *pos; 337 int blks, blk, dscrlen; 338 int i, error, sector_size; 339 340 sector_size = ump->discinfo.sector_size; 341 342 *dstp = dst = NULL; 343 dscrlen = sector_size; 344 345 /* read initial piece */ 346 error = udf_bread(ump, sector, &bp); 347 DPRINTFIF(DESCRIPTOR, error, ("read error (%d)\n", error)); 348 349 if (!error) { 350 /* check if its a valid tag */ 351 error = udf_check_tag(bp->b_data); 352 if (error) { 353 /* check if its an empty block */ 354 pos = bp->b_data; 355 for (i = 0; i < sector_size; i++, pos++) { 356 if (*pos) break; 357 } 358 if (i == sector_size) { 359 /* return no error but with no dscrptr */ 360 /* dispose first block */ 361 brelse(bp); 362 return 0; 363 } 364 } 365 } 366 DPRINTFIF(DESCRIPTOR, error, ("bad tag checksum\n")); 367 if (!error) { 368 src = (union dscrptr *) bp->b_data; 369 dscrlen = udf_tagsize(src, sector_size); 370 dst = malloc(dscrlen, mtype, M_WAITOK); 371 memcpy(dst, src, sector_size); 372 } 373 /* dispose first block */ 374 bp->b_flags |= B_AGE; 375 brelse(bp); 376 377 if (!error && (dscrlen > sector_size)) { 378 DPRINTF(DESCRIPTOR, ("multi block descriptor read\n")); 379 /* 380 * Read the rest of descriptor. Since it is only used at mount 381 * time its overdone to define and use a specific udf_breadn 382 * for this alone. 383 */ 384 blks = (dscrlen + sector_size -1) / sector_size; 385 for (blk = 1; blk < blks; blk++) { 386 error = udf_bread(ump, sector + blk, &bp); 387 if (error) { 388 brelse(bp); 389 break; 390 } 391 pos = (uint8_t *) dst + blk*sector_size; 392 memcpy(pos, bp->b_data, sector_size); 393 394 /* dispose block */ 395 bp->b_flags |= B_AGE; 396 brelse(bp); 397 } 398 DPRINTFIF(DESCRIPTOR, error, ("read error on multi (%d)\n", 399 error)); 400 } 401 if (!error) { 402 error = udf_check_tag_payload(dst, dscrlen); 403 DPRINTFIF(DESCRIPTOR, error, ("bad payload check sum\n")); 404 } 405 if (error && dst) { 406 free(dst, mtype); 407 dst = NULL; 408 } 409 *dstp = dst; 410 411 return error; 412 } 413 414 /* --------------------------------------------------------------------- */ 415 #ifdef DEBUG 416 static void 417 udf_dump_discinfo(struct udf_mount *ump) 418 { 419 char bits[128]; 420 struct mmc_discinfo *di = &ump->discinfo; 421 422 if ((udf_verbose & UDF_DEBUG_VOLUMES) == 0) 423 return; 424 425 printf("Device/media info :\n"); 426 printf("\tMMC profile 0x%02x\n", di->mmc_profile); 427 printf("\tderived class %d\n", di->mmc_class); 428 printf("\tsector size %d\n", di->sector_size); 429 printf("\tdisc state %d\n", di->disc_state); 430 printf("\tlast ses state %d\n", di->last_session_state); 431 printf("\tbg format state %d\n", di->bg_format_state); 432 printf("\tfrst track %d\n", di->first_track); 433 printf("\tfst on last ses %d\n", di->first_track_last_session); 434 printf("\tlst on last ses %d\n", di->last_track_last_session); 435 printf("\tlink block penalty %d\n", di->link_block_penalty); 436 bitmask_snprintf(di->disc_flags, MMC_DFLAGS_FLAGBITS, bits, 437 sizeof(bits)); 438 printf("\tdisc flags %s\n", bits); 439 printf("\tdisc id %x\n", di->disc_id); 440 printf("\tdisc barcode %"PRIx64"\n", di->disc_barcode); 441 442 printf("\tnum sessions %d\n", di->num_sessions); 443 printf("\tnum tracks %d\n", di->num_tracks); 444 445 bitmask_snprintf(di->mmc_cur, MMC_CAP_FLAGBITS, bits, sizeof(bits)); 446 printf("\tcapabilities cur %s\n", bits); 447 bitmask_snprintf(di->mmc_cap, MMC_CAP_FLAGBITS, bits, sizeof(bits)); 448 printf("\tcapabilities cap %s\n", bits); 449 } 450 #else 451 #define udf_dump_discinfo(a); 452 #endif 453 454 /* not called often */ 455 int 456 udf_update_discinfo(struct udf_mount *ump) 457 { 458 struct vnode *devvp = ump->devvp; 459 struct partinfo dpart; 460 struct mmc_discinfo *di; 461 int error; 462 463 DPRINTF(VOLUMES, ("read/update disc info\n")); 464 di = &ump->discinfo; 465 memset(di, 0, sizeof(struct mmc_discinfo)); 466 467 /* check if we're on a MMC capable device, i.e. CD/DVD */ 468 error = VOP_IOCTL(devvp, MMCGETDISCINFO, di, FKIOCTL, NOCRED, NULL); 469 if (error == 0) { 470 udf_dump_discinfo(ump); 471 return 0; 472 } 473 474 /* disc partition support */ 475 error = VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, NOCRED, NULL); 476 if (error) 477 return ENODEV; 478 479 /* set up a disc info profile for partitions */ 480 di->mmc_profile = 0x01; /* disc type */ 481 di->mmc_class = MMC_CLASS_DISC; 482 di->disc_state = MMC_STATE_CLOSED; 483 di->last_session_state = MMC_STATE_CLOSED; 484 di->bg_format_state = MMC_BGFSTATE_COMPLETED; 485 di->link_block_penalty = 0; 486 487 di->mmc_cur = MMC_CAP_RECORDABLE | MMC_CAP_REWRITABLE | 488 MMC_CAP_ZEROLINKBLK | MMC_CAP_HW_DEFECTFREE; 489 di->mmc_cap = di->mmc_cur; 490 di->disc_flags = MMC_DFLAGS_UNRESTRICTED; 491 492 /* TODO problem with last_possible_lba on resizable VND; request */ 493 di->last_possible_lba = dpart.part->p_size; 494 di->sector_size = dpart.disklab->d_secsize; 495 di->blockingnr = 1; 496 497 di->num_sessions = 1; 498 di->num_tracks = 1; 499 500 di->first_track = 1; 501 di->first_track_last_session = di->last_track_last_session = 1; 502 503 udf_dump_discinfo(ump); 504 return 0; 505 } 506 507 /* --------------------------------------------------------------------- */ 508 509 int 510 udf_update_trackinfo(struct udf_mount *ump, struct mmc_trackinfo *ti) 511 { 512 struct vnode *devvp = ump->devvp; 513 struct mmc_discinfo *di = &ump->discinfo; 514 int error, class; 515 516 DPRINTF(VOLUMES, ("read track info\n")); 517 518 class = di->mmc_class; 519 if (class != MMC_CLASS_DISC) { 520 /* tracknr specified in struct ti */ 521 error = VOP_IOCTL(devvp, MMCGETTRACKINFO, ti, FKIOCTL, 522 NOCRED, NULL); 523 return error; 524 } 525 526 /* disc partition support */ 527 if (ti->tracknr != 1) 528 return EIO; 529 530 /* create fake ti (TODO check for resized vnds) */ 531 ti->sessionnr = 1; 532 533 ti->track_mode = 0; /* XXX */ 534 ti->data_mode = 0; /* XXX */ 535 ti->flags = MMC_TRACKINFO_LRA_VALID | MMC_TRACKINFO_NWA_VALID; 536 537 ti->track_start = 0; 538 ti->packet_size = 1; 539 540 /* TODO support for resizable vnd */ 541 ti->track_size = di->last_possible_lba; 542 ti->next_writable = di->last_possible_lba; 543 ti->last_recorded = ti->next_writable; 544 ti->free_blocks = 0; 545 546 return 0; 547 } 548 549 /* --------------------------------------------------------------------- */ 550 551 /* track/session searching for mounting */ 552 553 static int 554 udf_search_tracks(struct udf_mount *ump, struct udf_args *args, 555 int *first_tracknr, int *last_tracknr) 556 { 557 struct mmc_trackinfo trackinfo; 558 uint32_t tracknr, start_track, num_tracks; 559 int error; 560 561 /* if negative, sessionnr is relative to last session */ 562 if (args->sessionnr < 0) { 563 args->sessionnr += ump->discinfo.num_sessions; 564 /* sanity */ 565 if (args->sessionnr < 0) 566 args->sessionnr = 0; 567 } 568 569 /* sanity */ 570 if (args->sessionnr > ump->discinfo.num_sessions) 571 args->sessionnr = ump->discinfo.num_sessions; 572 573 /* search the tracks for this session, zero session nr indicates last */ 574 if (args->sessionnr == 0) { 575 args->sessionnr = ump->discinfo.num_sessions; 576 if (ump->discinfo.last_session_state == MMC_STATE_EMPTY) { 577 args->sessionnr--; 578 } 579 } 580 581 /* search the first and last track of the specified session */ 582 num_tracks = ump->discinfo.num_tracks; 583 start_track = ump->discinfo.first_track; 584 585 /* search for first track of this session */ 586 for (tracknr = start_track; tracknr <= num_tracks; tracknr++) { 587 /* get track info */ 588 trackinfo.tracknr = tracknr; 589 error = udf_update_trackinfo(ump, &trackinfo); 590 if (error) 591 return error; 592 593 if (trackinfo.sessionnr == args->sessionnr) 594 break; 595 } 596 *first_tracknr = tracknr; 597 598 /* search for last track of this session */ 599 for (;tracknr <= num_tracks; tracknr++) { 600 /* get track info */ 601 trackinfo.tracknr = tracknr; 602 error = udf_update_trackinfo(ump, &trackinfo); 603 if (error || (trackinfo.sessionnr != args->sessionnr)) { 604 tracknr--; 605 break; 606 } 607 } 608 if (tracknr > num_tracks) 609 tracknr--; 610 611 *last_tracknr = tracknr; 612 613 assert(*last_tracknr >= *first_tracknr); 614 return 0; 615 } 616 617 /* --------------------------------------------------------------------- */ 618 619 static int 620 udf_read_anchor(struct udf_mount *ump, uint32_t sector, struct anchor_vdp **dst) 621 { 622 int error; 623 624 error = udf_read_descriptor(ump, sector, M_UDFVOLD, 625 (union dscrptr **) dst); 626 if (!error) { 627 /* blank terminator blocks are not allowed here */ 628 if (*dst == NULL) 629 return ENOENT; 630 if (udf_rw16((*dst)->tag.id) != TAGID_ANCHOR) { 631 error = ENOENT; 632 free(*dst, M_UDFVOLD); 633 *dst = NULL; 634 DPRINTF(VOLUMES, ("Not an anchor\n")); 635 } 636 } 637 638 return error; 639 } 640 641 642 int 643 udf_read_anchors(struct udf_mount *ump, struct udf_args *args) 644 { 645 struct mmc_trackinfo first_track; 646 struct mmc_trackinfo last_track; 647 struct anchor_vdp **anchorsp; 648 uint32_t track_start; 649 uint32_t track_end; 650 uint32_t positions[4]; 651 int first_tracknr, last_tracknr; 652 int error, anch, ok, first_anchor; 653 654 /* search the first and last track of the specified session */ 655 error = udf_search_tracks(ump, args, &first_tracknr, &last_tracknr); 656 if (!error) { 657 first_track.tracknr = first_tracknr; 658 error = udf_update_trackinfo(ump, &first_track); 659 } 660 if (!error) { 661 last_track.tracknr = last_tracknr; 662 error = udf_update_trackinfo(ump, &last_track); 663 } 664 if (error) { 665 printf("UDF mount: reading disc geometry failed\n"); 666 return 0; 667 } 668 669 track_start = first_track.track_start; 670 671 /* `end' is not as straitforward as start. */ 672 track_end = last_track.track_start 673 + last_track.track_size - last_track.free_blocks - 1; 674 675 if (ump->discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) { 676 /* end of track is not straitforward here */ 677 if (last_track.flags & MMC_TRACKINFO_LRA_VALID) 678 track_end = last_track.last_recorded; 679 else if (last_track.flags & MMC_TRACKINFO_NWA_VALID) 680 track_end = last_track.next_writable 681 - ump->discinfo.link_block_penalty; 682 } 683 684 /* its no use reading a blank track */ 685 first_anchor = 0; 686 if (first_track.flags & MMC_TRACKINFO_BLANK) 687 first_anchor = 1; 688 689 /* read anchors start+256, start+512, end-256, end */ 690 positions[0] = track_start+256; 691 positions[1] = track_end-256; 692 positions[2] = track_end; 693 positions[3] = track_start+512; /* [UDF 2.60/6.11.2] */ 694 /* XXX shouldn't +512 be prefered above +256 for compat with Roxio CD */ 695 696 ok = 0; 697 anchorsp = ump->anchors; 698 for (anch = first_anchor; anch < 4; anch++) { 699 DPRINTF(VOLUMES, ("Read anchor %d at sector %d\n", anch, 700 positions[anch])); 701 error = udf_read_anchor(ump, positions[anch], anchorsp); 702 if (!error) { 703 anchorsp++; 704 ok++; 705 } 706 } 707 708 /* VATs are only recorded on sequential media, but initialise */ 709 ump->first_possible_vat_location = track_start + 256 + 1; 710 ump->last_possible_vat_location = track_end 711 + ump->discinfo.blockingnr; 712 713 return ok; 714 } 715 716 /* --------------------------------------------------------------------- */ 717 718 /* we dont try to be smart; we just record the parts */ 719 #define UDF_UPDATE_DSCR(name, dscr) \ 720 if (name) \ 721 free(name, M_UDFVOLD); \ 722 name = dscr; 723 724 static int 725 udf_process_vds_descriptor(struct udf_mount *ump, union dscrptr *dscr) 726 { 727 uint16_t partnr; 728 729 DPRINTF(VOLUMES, ("\tprocessing VDS descr %d\n", 730 udf_rw16(dscr->tag.id))); 731 switch (udf_rw16(dscr->tag.id)) { 732 case TAGID_PRI_VOL : /* primary partition */ 733 UDF_UPDATE_DSCR(ump->primary_vol, &dscr->pvd); 734 break; 735 case TAGID_LOGVOL : /* logical volume */ 736 UDF_UPDATE_DSCR(ump->logical_vol, &dscr->lvd); 737 break; 738 case TAGID_UNALLOC_SPACE : /* unallocated space */ 739 UDF_UPDATE_DSCR(ump->unallocated, &dscr->usd); 740 break; 741 case TAGID_IMP_VOL : /* implementation */ 742 /* XXX do we care about multiple impl. descr ? */ 743 UDF_UPDATE_DSCR(ump->implementation, &dscr->ivd); 744 break; 745 case TAGID_PARTITION : /* physical partition */ 746 /* not much use if its not allocated */ 747 if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) { 748 free(dscr, M_UDFVOLD); 749 break; 750 } 751 752 /* check partnr boundaries */ 753 partnr = udf_rw16(dscr->pd.part_num); 754 if (partnr >= UDF_PARTITIONS) 755 return EINVAL; 756 757 UDF_UPDATE_DSCR(ump->partitions[partnr], &dscr->pd); 758 break; 759 case TAGID_VOL : /* volume space extender; rare */ 760 DPRINTF(VOLUMES, ("VDS extender ignored\n")); 761 free(dscr, M_UDFVOLD); 762 break; 763 default : 764 DPRINTF(VOLUMES, ("Unhandled VDS type %d\n", 765 udf_rw16(dscr->tag.id))); 766 free(dscr, M_UDFVOLD); 767 } 768 769 return 0; 770 } 771 #undef UDF_UPDATE_DSCR 772 773 /* --------------------------------------------------------------------- */ 774 775 static int 776 udf_read_vds_extent(struct udf_mount *ump, uint32_t loc, uint32_t len) 777 { 778 union dscrptr *dscr; 779 uint32_t sector_size, dscr_size; 780 int error; 781 782 sector_size = ump->discinfo.sector_size; 783 784 /* loc is sectornr, len is in bytes */ 785 error = EIO; 786 while (len) { 787 error = udf_read_descriptor(ump, loc, M_UDFVOLD, &dscr); 788 if (error) 789 return error; 790 791 /* blank block is a terminator */ 792 if (dscr == NULL) 793 return 0; 794 795 /* TERM descriptor is a terminator */ 796 if (udf_rw16(dscr->tag.id) == TAGID_TERM) 797 return 0; 798 799 /* process all others */ 800 dscr_size = udf_tagsize(dscr, sector_size); 801 error = udf_process_vds_descriptor(ump, dscr); 802 if (error) { 803 free(dscr, M_UDFVOLD); 804 break; 805 } 806 assert((dscr_size % sector_size) == 0); 807 808 len -= dscr_size; 809 loc += dscr_size / sector_size; 810 } 811 812 return error; 813 } 814 815 816 int 817 udf_read_vds_space(struct udf_mount *ump) 818 { 819 struct anchor_vdp *anchor, *anchor2; 820 size_t size; 821 uint32_t main_loc, main_len; 822 uint32_t reserve_loc, reserve_len; 823 int error; 824 825 /* 826 * read in VDS space provided by the anchors; if one descriptor read 827 * fails, try the mirror sector. 828 * 829 * check if 2nd anchor is different from 1st; if so, go for 2nd. This 830 * avoids the `compatibility features' of DirectCD that may confuse 831 * stuff completely. 832 */ 833 834 anchor = ump->anchors[0]; 835 anchor2 = ump->anchors[1]; 836 assert(anchor); 837 838 if (anchor2) { 839 size = sizeof(struct extent_ad); 840 if (memcmp(&anchor->main_vds_ex, &anchor2->main_vds_ex, size)) 841 anchor = anchor2; 842 /* reserve is specified to be a literal copy of main */ 843 } 844 845 main_loc = udf_rw32(anchor->main_vds_ex.loc); 846 main_len = udf_rw32(anchor->main_vds_ex.len); 847 848 reserve_loc = udf_rw32(anchor->reserve_vds_ex.loc); 849 reserve_len = udf_rw32(anchor->reserve_vds_ex.len); 850 851 error = udf_read_vds_extent(ump, main_loc, main_len); 852 if (error) { 853 printf("UDF mount: reading in reserve VDS extent\n"); 854 error = udf_read_vds_extent(ump, reserve_loc, reserve_len); 855 } 856 857 return error; 858 } 859 860 /* --------------------------------------------------------------------- */ 861 862 /* 863 * Read in the logical volume integrity sequence pointed to by our logical 864 * volume descriptor. Its a sequence that can be extended using fields in the 865 * integrity descriptor itself. On sequential media only one is found, on 866 * rewritable media a sequence of descriptors can be found as a form of 867 * history keeping and on non sequential write-once media the chain is vital 868 * to allow more and more descriptors to be written. The last descriptor 869 * written in an extent needs to claim space for a new extent. 870 */ 871 872 static int 873 udf_retrieve_lvint(struct udf_mount *ump, struct logvol_int_desc **lvintp) 874 { 875 union dscrptr *dscr; 876 struct logvol_int_desc *lvint; 877 uint32_t sector_size, sector, len; 878 int dscr_type, error; 879 880 sector_size = ump->discinfo.sector_size; 881 len = udf_rw32(ump->logical_vol->integrity_seq_loc.len); 882 sector = udf_rw32(ump->logical_vol->integrity_seq_loc.loc); 883 884 lvint = NULL; 885 dscr = NULL; 886 error = 0; 887 while (len) { 888 /* read in our integrity descriptor */ 889 error = udf_read_descriptor(ump, sector, M_UDFVOLD, &dscr); 890 if (!error) { 891 if (dscr == NULL) 892 break; /* empty terminates */ 893 dscr_type = udf_rw16(dscr->tag.id); 894 if (dscr_type == TAGID_TERM) { 895 break; /* clean terminator */ 896 } 897 if (dscr_type != TAGID_LOGVOL_INTEGRITY) { 898 /* fatal... corrupt disc */ 899 error = ENOENT; 900 break; 901 } 902 if (lvint) 903 free(lvint, M_UDFVOLD); 904 lvint = &dscr->lvid; 905 dscr = NULL; 906 } /* else hope for the best... maybe the next is ok */ 907 908 DPRINTFIF(VOLUMES, lvint, ("logvol integrity read, state %s\n", 909 udf_rw32(lvint->integrity_type) ? "CLOSED" : "OPEN")); 910 911 /* proceed sequential */ 912 sector += 1; 913 len -= sector_size; 914 915 /* are we linking to a new piece? */ 916 if (lvint->next_extent.len) { 917 len = udf_rw32(lvint->next_extent.len); 918 sector = udf_rw32(lvint->next_extent.loc); 919 } 920 } 921 922 /* clean up the mess, esp. when there is an error */ 923 if (dscr) 924 free(dscr, M_UDFVOLD); 925 926 if (error && lvint) { 927 free(lvint, M_UDFVOLD); 928 lvint = NULL; 929 } 930 931 if (!lvint) 932 error = ENOENT; 933 934 *lvintp = lvint; 935 return error; 936 } 937 938 /* --------------------------------------------------------------------- */ 939 940 /* 941 * Checks if ump's vds information is correct and complete 942 */ 943 944 int 945 udf_process_vds(struct udf_mount *ump, struct udf_args *args) { 946 union udf_pmap *mapping; 947 struct logvol_int_desc *lvint; 948 struct udf_logvol_info *lvinfo; 949 uint32_t n_pm, mt_l; 950 uint8_t *pmap_pos; 951 char *domain_name, *map_name; 952 const char *check_name; 953 int pmap_stype, pmap_size; 954 int pmap_type, log_part, phys_part; 955 int n_phys, n_virt, n_spar, n_meta; 956 int len, error; 957 958 if (ump == NULL) 959 return ENOENT; 960 961 /* we need at least an anchor (trivial, but for safety) */ 962 if (ump->anchors[0] == NULL) 963 return EINVAL; 964 965 /* we need at least one primary and one logical volume descriptor */ 966 if ((ump->primary_vol == NULL) || (ump->logical_vol) == NULL) 967 return EINVAL; 968 969 /* we need at least one partition descriptor */ 970 if (ump->partitions[0] == NULL) 971 return EINVAL; 972 973 /* check logical volume sector size verses device sector size */ 974 if (udf_rw32(ump->logical_vol->lb_size) != ump->discinfo.sector_size) { 975 printf("UDF mount: format violation, lb_size != sector size\n"); 976 return EINVAL; 977 } 978 979 domain_name = ump->logical_vol->domain_id.id; 980 if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) { 981 printf("mount_udf: disc not OSTA UDF Compliant, aborting\n"); 982 return EINVAL; 983 } 984 985 /* retrieve logical volume integrity sequence */ 986 error = udf_retrieve_lvint(ump, &ump->logvol_integrity); 987 988 /* 989 * We need at least one logvol integrity descriptor recorded. Note 990 * that its OK to have an open logical volume integrity here. The VAT 991 * will close/update the integrity. 992 */ 993 if (ump->logvol_integrity == NULL) 994 return EINVAL; 995 996 /* process derived structures */ 997 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 998 lvint = ump->logvol_integrity; 999 lvinfo = (struct udf_logvol_info *) (&lvint->tables[2 * n_pm]); 1000 ump->logvol_info = lvinfo; 1001 1002 /* TODO check udf versions? */ 1003 1004 /* 1005 * check logvol mappings: effective virt->log partmap translation 1006 * check and recording of the mapping results. Saves expensive 1007 * strncmp() in tight places. 1008 */ 1009 DPRINTF(VOLUMES, ("checking logvol mappings\n")); 1010 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1011 mt_l = udf_rw32(ump->logical_vol->mt_l); /* partmaps data length */ 1012 pmap_pos = ump->logical_vol->maps; 1013 1014 if (n_pm > UDF_PMAPS) { 1015 printf("UDF mount: too many mappings\n"); 1016 return EINVAL; 1017 } 1018 1019 n_phys = n_virt = n_spar = n_meta = 0; 1020 for (log_part = 0; log_part < n_pm; log_part++) { 1021 mapping = (union udf_pmap *) pmap_pos; 1022 pmap_stype = pmap_pos[0]; 1023 pmap_size = pmap_pos[1]; 1024 switch (pmap_stype) { 1025 case 1: /* physical mapping */ 1026 /* volseq = udf_rw16(mapping->pm1.vol_seq_num); */ 1027 phys_part = udf_rw16(mapping->pm1.part_num); 1028 pmap_type = UDF_VTOP_TYPE_PHYS; 1029 n_phys++; 1030 break; 1031 case 2: /* virtual/sparable/meta mapping */ 1032 map_name = mapping->pm2.part_id.id; 1033 /* volseq = udf_rw16(mapping->pm2.vol_seq_num); */ 1034 phys_part = udf_rw16(mapping->pm2.part_num); 1035 pmap_type = UDF_VTOP_TYPE_UNKNOWN; 1036 len = UDF_REGID_ID_SIZE; 1037 1038 check_name = "*UDF Virtual Partition"; 1039 if (strncmp(map_name, check_name, len) == 0) { 1040 pmap_type = UDF_VTOP_TYPE_VIRT; 1041 n_virt++; 1042 break; 1043 } 1044 check_name = "*UDF Sparable Partition"; 1045 if (strncmp(map_name, check_name, len) == 0) { 1046 pmap_type = UDF_VTOP_TYPE_SPARABLE; 1047 n_spar++; 1048 break; 1049 } 1050 check_name = "*UDF Metadata Partition"; 1051 if (strncmp(map_name, check_name, len) == 0) { 1052 pmap_type = UDF_VTOP_TYPE_META; 1053 n_meta++; 1054 break; 1055 } 1056 break; 1057 default: 1058 return EINVAL; 1059 } 1060 1061 DPRINTF(VOLUMES, ("\t%d -> %d type %d\n", log_part, phys_part, 1062 pmap_type)); 1063 if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) 1064 return EINVAL; 1065 1066 ump->vtop [log_part] = phys_part; 1067 ump->vtop_tp[log_part] = pmap_type; 1068 1069 pmap_pos += pmap_size; 1070 } 1071 /* not winning the beauty contest */ 1072 ump->vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW; 1073 1074 /* test some basic UDF assertions/requirements */ 1075 if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1)) 1076 return EINVAL; 1077 1078 if (n_virt) { 1079 if ((n_phys == 0) || n_spar || n_meta) 1080 return EINVAL; 1081 } 1082 if (n_spar + n_phys == 0) 1083 return EINVAL; 1084 1085 /* vat's can only be on a sequential media */ 1086 ump->data_alloc = UDF_ALLOC_SPACEMAP; 1087 if (n_virt) 1088 ump->data_alloc = UDF_ALLOC_SEQUENTIAL; 1089 1090 ump->meta_alloc = UDF_ALLOC_SPACEMAP; 1091 if (n_virt) 1092 ump->meta_alloc = UDF_ALLOC_VAT; 1093 if (n_meta) 1094 ump->meta_alloc = UDF_ALLOC_METABITMAP; 1095 1096 /* special cases for pseudo-overwrite */ 1097 if (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) { 1098 ump->data_alloc = UDF_ALLOC_SEQUENTIAL; 1099 if (n_meta) { 1100 ump->meta_alloc = UDF_ALLOC_METASEQUENTIAL; 1101 } else { 1102 ump->meta_alloc = UDF_ALLOC_RELAXEDSEQUENTIAL; 1103 } 1104 } 1105 1106 DPRINTF(VOLUMES, ("\tdata alloc scheme %d, meta alloc scheme %d\n", 1107 ump->data_alloc, ump->meta_alloc)); 1108 /* TODO determine partitions to write data and metadata ? */ 1109 1110 /* signal its OK for now */ 1111 return 0; 1112 } 1113 1114 /* --------------------------------------------------------------------- */ 1115 1116 /* 1117 * Read in complete VAT file and check if its indeed a VAT file descriptor 1118 */ 1119 1120 static int 1121 udf_check_for_vat(struct udf_node *vat_node) 1122 { 1123 struct udf_mount *ump; 1124 struct icb_tag *icbtag; 1125 struct timestamp *mtime; 1126 struct regid *regid; 1127 struct udf_vat *vat; 1128 struct udf_logvol_info *lvinfo; 1129 uint32_t vat_length, alloc_length; 1130 uint32_t vat_offset, vat_entries; 1131 uint32_t sector_size; 1132 uint32_t sectors; 1133 uint32_t *raw_vat; 1134 char *regid_name; 1135 int filetype; 1136 int error; 1137 1138 /* vat_length is really 64 bits though impossible */ 1139 1140 DPRINTF(VOLUMES, ("Checking for VAT\n")); 1141 if (!vat_node) 1142 return ENOENT; 1143 1144 /* get mount info */ 1145 ump = vat_node->ump; 1146 1147 /* check assertions */ 1148 assert(vat_node->fe || vat_node->efe); 1149 assert(ump->logvol_integrity); 1150 1151 /* get information from fe/efe */ 1152 if (vat_node->fe) { 1153 vat_length = udf_rw64(vat_node->fe->inf_len); 1154 icbtag = &vat_node->fe->icbtag; 1155 mtime = &vat_node->fe->mtime; 1156 } else { 1157 vat_length = udf_rw64(vat_node->efe->inf_len); 1158 icbtag = &vat_node->efe->icbtag; 1159 mtime = &vat_node->efe->mtime; 1160 } 1161 1162 /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */ 1163 filetype = icbtag->file_type; 1164 if ((filetype != 0) && (filetype != UDF_ICB_FILETYPE_VAT)) 1165 return ENOENT; 1166 1167 DPRINTF(VOLUMES, ("\tPossible VAT length %d\n", vat_length)); 1168 /* place a sanity check on the length; currently 1Mb in size */ 1169 if (vat_length > 1*1024*1024) 1170 return ENOENT; 1171 1172 /* get sector size */ 1173 sector_size = vat_node->ump->discinfo.sector_size; 1174 1175 /* calculate how many sectors to read in and how much to allocate */ 1176 sectors = (vat_length + sector_size -1) / sector_size; 1177 alloc_length = (sectors + 2) * sector_size; 1178 1179 /* try to allocate the space */ 1180 ump->vat_table_alloc_length = alloc_length; 1181 ump->vat_table = malloc(alloc_length, M_UDFMNT, M_CANFAIL | M_WAITOK); 1182 if (!ump->vat_table) 1183 return ENOMEM; /* impossible to allocate */ 1184 DPRINTF(VOLUMES, ("\talloced fine\n")); 1185 1186 /* read it in! */ 1187 raw_vat = (uint32_t *) ump->vat_table; 1188 error = udf_read_file_extent(vat_node, 0, sectors, (uint8_t *) raw_vat); 1189 if (error) { 1190 DPRINTF(VOLUMES, ("\tread failed : %d\n", error)); 1191 /* not completely readable... :( bomb out */ 1192 free(ump->vat_table, M_UDFMNT); 1193 ump->vat_table = NULL; 1194 return error; 1195 } 1196 DPRINTF(VOLUMES, ("VAT read in fine!\n")); 1197 1198 /* 1199 * check contents of the file if its the old 1.50 VAT table format. 1200 * Its notoriously broken and allthough some implementations support an 1201 * extention as defined in the UDF 1.50 errata document, its doubtfull 1202 * to be useable since a lot of implementations don't maintain it. 1203 */ 1204 lvinfo = ump->logvol_info; 1205 1206 if (filetype == 0) { 1207 /* definition */ 1208 vat_offset = 0; 1209 vat_entries = (vat_length-36)/4; 1210 1211 /* check 1.50 VAT */ 1212 regid = (struct regid *) (raw_vat + vat_entries); 1213 regid_name = (char *) regid->id; 1214 error = strncmp(regid_name, "*UDF Virtual Alloc Tbl", 22); 1215 if (error) { 1216 DPRINTF(VOLUMES, ("VAT format 1.50 rejected\n")); 1217 free(ump->vat_table, M_UDFMNT); 1218 ump->vat_table = NULL; 1219 return ENOENT; 1220 } 1221 /* TODO update LVID from "*UDF VAT LVExtension" ext. attr. */ 1222 } else { 1223 vat = (struct udf_vat *) raw_vat; 1224 1225 /* definition */ 1226 vat_offset = vat->header_len; 1227 vat_entries = (vat_length - vat_offset)/4; 1228 1229 assert(lvinfo); 1230 lvinfo->num_files = vat->num_files; 1231 lvinfo->num_directories = vat->num_directories; 1232 lvinfo->min_udf_readver = vat->min_udf_readver; 1233 lvinfo->min_udf_writever = vat->min_udf_writever; 1234 lvinfo->max_udf_writever = vat->max_udf_writever; 1235 } 1236 1237 ump->vat_offset = vat_offset; 1238 ump->vat_entries = vat_entries; 1239 1240 DPRINTF(VOLUMES, ("VAT format accepted, marking it closed\n")); 1241 ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED); 1242 ump->logvol_integrity->time = *mtime; 1243 1244 return 0; /* success! */ 1245 } 1246 1247 /* --------------------------------------------------------------------- */ 1248 1249 static int 1250 udf_search_vat(struct udf_mount *ump, union udf_pmap *mapping) 1251 { 1252 struct udf_node *vat_node; 1253 struct long_ad icb_loc; 1254 uint32_t early_vat_loc, late_vat_loc, vat_loc; 1255 int error; 1256 1257 /* mapping info not needed */ 1258 mapping = mapping; 1259 1260 vat_loc = ump->last_possible_vat_location; 1261 early_vat_loc = vat_loc - 2 * ump->discinfo.blockingnr; 1262 early_vat_loc = MAX(early_vat_loc, ump->first_possible_vat_location); 1263 late_vat_loc = vat_loc + 1024; 1264 1265 /* TODO first search last sector? */ 1266 do { 1267 DPRINTF(VOLUMES, ("Checking for VAT at sector %d\n", vat_loc)); 1268 icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART); 1269 icb_loc.loc.lb_num = udf_rw32(vat_loc); 1270 1271 error = udf_get_node(ump, &icb_loc, &vat_node); 1272 if (!error) error = udf_check_for_vat(vat_node); 1273 if (!error) break; 1274 if (vat_node) { 1275 vput(vat_node->vnode); 1276 udf_dispose_node(vat_node); 1277 } 1278 vat_loc--; /* walk backwards */ 1279 } while (vat_loc >= early_vat_loc); 1280 1281 /* we don't need our VAT node anymore */ 1282 if (vat_node) { 1283 vput(vat_node->vnode); 1284 udf_dispose_node(vat_node); 1285 } 1286 1287 return error; 1288 } 1289 1290 /* --------------------------------------------------------------------- */ 1291 1292 static int 1293 udf_read_sparables(struct udf_mount *ump, union udf_pmap *mapping) 1294 { 1295 union dscrptr *dscr; 1296 struct part_map_spare *pms = (struct part_map_spare *) mapping; 1297 uint32_t lb_num; 1298 int spar, error; 1299 1300 /* 1301 * The partition mapping passed on to us specifies the information we 1302 * need to locate and initialise the sparable partition mapping 1303 * information we need. 1304 */ 1305 1306 DPRINTF(VOLUMES, ("Read sparable table\n")); 1307 ump->sparable_packet_len = udf_rw16(pms->packet_len); 1308 for (spar = 0; spar < pms->n_st; spar++) { 1309 lb_num = pms->st_loc[spar]; 1310 DPRINTF(VOLUMES, ("Checking for sparing table %d\n", lb_num)); 1311 error = udf_read_descriptor(ump, lb_num, M_UDFVOLD, &dscr); 1312 if (!error && dscr) { 1313 if (udf_rw16(dscr->tag.id) == TAGID_SPARING_TABLE) { 1314 if (ump->sparing_table) 1315 free(ump->sparing_table, M_UDFVOLD); 1316 ump->sparing_table = &dscr->spt; 1317 dscr = NULL; 1318 DPRINTF(VOLUMES, 1319 ("Sparing table accepted (%d entries)\n", 1320 udf_rw16(ump->sparing_table->rt_l))); 1321 break; /* we're done */ 1322 } 1323 } 1324 if (dscr) 1325 free(dscr, M_UDFVOLD); 1326 } 1327 1328 if (ump->sparing_table) 1329 return 0; 1330 1331 return ENOENT; 1332 } 1333 1334 /* --------------------------------------------------------------------- */ 1335 1336 int 1337 udf_read_vds_tables(struct udf_mount *ump, struct udf_args *args) 1338 { 1339 union udf_pmap *mapping; 1340 uint32_t n_pm, mt_l; 1341 uint32_t log_part; 1342 uint8_t *pmap_pos; 1343 int pmap_size; 1344 int error; 1345 1346 /* We have to iterate again over the part mappings for locations */ 1347 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1348 mt_l = udf_rw32(ump->logical_vol->mt_l); /* partmaps data length */ 1349 pmap_pos = ump->logical_vol->maps; 1350 1351 for (log_part = 0; log_part < n_pm; log_part++) { 1352 mapping = (union udf_pmap *) pmap_pos; 1353 switch (ump->vtop_tp[log_part]) { 1354 case UDF_VTOP_TYPE_PHYS : 1355 /* nothing */ 1356 break; 1357 case UDF_VTOP_TYPE_VIRT : 1358 /* search and load VAT */ 1359 error = udf_search_vat(ump, mapping); 1360 if (error) 1361 return ENOENT; 1362 break; 1363 case UDF_VTOP_TYPE_SPARABLE : 1364 /* load one of the sparable tables */ 1365 error = udf_read_sparables(ump, mapping); 1366 break; 1367 case UDF_VTOP_TYPE_META : 1368 /* TODO load metafile and metabitmapfile FE/EFEs */ 1369 break; 1370 default: 1371 break; 1372 } 1373 pmap_size = pmap_pos[1]; 1374 pmap_pos += pmap_size; 1375 } 1376 1377 return 0; 1378 } 1379 1380 /* --------------------------------------------------------------------- */ 1381 1382 int 1383 udf_read_rootdirs(struct udf_mount *ump, struct udf_args *args) 1384 { 1385 struct udf_node *rootdir_node, *streamdir_node; 1386 union dscrptr *dscr; 1387 struct long_ad fsd_loc, *dir_loc; 1388 uint32_t lb_num, dummy; 1389 uint32_t fsd_len; 1390 int dscr_type; 1391 int error; 1392 1393 /* TODO implement FSD reading in seperate function like integrity? */ 1394 /* get fileset descriptor sequence */ 1395 fsd_loc = ump->logical_vol->lv_fsd_loc; 1396 fsd_len = udf_rw32(fsd_loc.len); 1397 1398 dscr = NULL; 1399 error = 0; 1400 while (fsd_len || error) { 1401 DPRINTF(VOLUMES, ("fsd_len = %d\n", fsd_len)); 1402 /* translate fsd_loc to lb_num */ 1403 error = udf_translate_vtop(ump, &fsd_loc, &lb_num, &dummy); 1404 if (error) 1405 break; 1406 DPRINTF(VOLUMES, ("Reading FSD at lb %d\n", lb_num)); 1407 error = udf_read_descriptor(ump, lb_num, M_UDFVOLD, &dscr); 1408 /* end markers */ 1409 if (error || (dscr == NULL)) 1410 break; 1411 1412 /* analyse */ 1413 dscr_type = udf_rw16(dscr->tag.id); 1414 if (dscr_type == TAGID_TERM) 1415 break; 1416 if (dscr_type != TAGID_FSD) { 1417 free(dscr, M_UDFVOLD); 1418 return ENOENT; 1419 } 1420 1421 /* 1422 * TODO check for multiple fileset descriptors; its only 1423 * picking the last now. Also check for FSD 1424 * correctness/interpretability 1425 */ 1426 1427 /* update */ 1428 if (ump->fileset_desc) { 1429 free(ump->fileset_desc, M_UDFVOLD); 1430 } 1431 ump->fileset_desc = &dscr->fsd; 1432 dscr = NULL; 1433 1434 /* continue to the next fsd */ 1435 fsd_len -= ump->discinfo.sector_size; 1436 fsd_loc.loc.lb_num = udf_rw32(udf_rw32(fsd_loc.loc.lb_num)+1); 1437 1438 /* follow up to fsd->next_ex (long_ad) if its not null */ 1439 if (udf_rw32(ump->fileset_desc->next_ex.len)) { 1440 DPRINTF(VOLUMES, ("follow up FSD extent\n")); 1441 fsd_loc = ump->fileset_desc->next_ex; 1442 fsd_len = udf_rw32(ump->fileset_desc->next_ex.len); 1443 } 1444 } 1445 if (dscr) 1446 free(dscr, M_UDFVOLD); 1447 1448 /* there has to be one */ 1449 if (ump->fileset_desc == NULL) 1450 return ENOENT; 1451 1452 DPRINTF(VOLUMES, ("FSD read in fine\n")); 1453 1454 /* 1455 * Now the FSD is known, read in the rootdirectory and if one exists, 1456 * the system stream dir. Some files in the system streamdir are not 1457 * wanted in this implementation since they are not maintained. If 1458 * writing is enabled we'll delete these files if they exist. 1459 */ 1460 1461 rootdir_node = streamdir_node = NULL; 1462 dir_loc = NULL; 1463 1464 /* try to read in the rootdir */ 1465 dir_loc = &ump->fileset_desc->rootdir_icb; 1466 error = udf_get_node(ump, dir_loc, &rootdir_node); 1467 if (error) 1468 return ENOENT; 1469 1470 /* aparently it read in fine */ 1471 1472 /* 1473 * Try the system stream directory; not very likely in the ones we 1474 * test, but for completeness. 1475 */ 1476 dir_loc = &ump->fileset_desc->streamdir_icb; 1477 if (udf_rw32(dir_loc->len)) { 1478 error = udf_get_node(ump, dir_loc, &streamdir_node); 1479 if (error) 1480 printf("udf mount: streamdir defined but ignored\n"); 1481 if (!error) { 1482 /* 1483 * TODO process streamdir `baddies' i.e. files we dont 1484 * want if R/W 1485 */ 1486 } 1487 } 1488 1489 DPRINTF(VOLUMES, ("Rootdir(s) read in fine\n")); 1490 1491 /* release the vnodes again; they'll be auto-recycled later */ 1492 if (streamdir_node) { 1493 vput(streamdir_node->vnode); 1494 } 1495 if (rootdir_node) { 1496 vput(rootdir_node->vnode); 1497 } 1498 1499 return 0; 1500 } 1501 1502 /* --------------------------------------------------------------------- */ 1503 1504 int 1505 udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc, 1506 uint32_t *lb_numres, uint32_t *extres) 1507 { 1508 struct part_desc *pdesc; 1509 struct spare_map_entry *sme; 1510 uint32_t *trans; 1511 uint32_t lb_num, lb_rel, lb_packet; 1512 int rel, vpart, part; 1513 1514 assert(ump && icb_loc && lb_numres); 1515 1516 vpart = udf_rw16(icb_loc->loc.part_num); 1517 lb_num = udf_rw32(icb_loc->loc.lb_num); 1518 if (vpart < 0 || vpart > UDF_VTOP_RAWPART) 1519 return EINVAL; 1520 1521 switch (ump->vtop_tp[vpart]) { 1522 case UDF_VTOP_TYPE_RAW : 1523 /* 1:1 to the end of the device */ 1524 *lb_numres = lb_num; 1525 *extres = INT_MAX; 1526 return 0; 1527 case UDF_VTOP_TYPE_PHYS : 1528 /* transform into its disc logical block */ 1529 part = ump->vtop[vpart]; 1530 pdesc = ump->partitions[part]; 1531 if (lb_num > udf_rw32(pdesc->part_len)) 1532 return EINVAL; 1533 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1534 1535 /* extent from here to the end of the partition */ 1536 *extres = udf_rw32(pdesc->part_len) - lb_num; 1537 return 0; 1538 case UDF_VTOP_TYPE_VIRT : 1539 /* only maps one sector, lookup in VAT */ 1540 if (lb_num >= ump->vat_entries) /* XXX > or >= ? */ 1541 return EINVAL; 1542 1543 /* lookup in virtual allocation table */ 1544 trans = (uint32_t *) (ump->vat_table + ump->vat_offset); 1545 lb_num = udf_rw32(trans[lb_num]); 1546 1547 /* transform into its disc logical block */ 1548 part = ump->vtop[vpart]; 1549 pdesc = ump->partitions[part]; 1550 if (lb_num > udf_rw32(pdesc->part_len)) 1551 return EINVAL; 1552 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1553 1554 /* just one logical block */ 1555 *extres = 1; 1556 return 0; 1557 case UDF_VTOP_TYPE_SPARABLE : 1558 /* check if the packet containing the lb_num is remapped */ 1559 lb_packet = lb_num / ump->sparable_packet_len; 1560 lb_rel = lb_num % ump->sparable_packet_len; 1561 1562 for (rel = 0; rel < udf_rw16(ump->sparing_table->rt_l); rel++) { 1563 sme = &ump->sparing_table->entries[rel]; 1564 if (lb_packet == udf_rw32(sme->org)) { 1565 /* NOTE maps to absolute disc logical block! */ 1566 *lb_numres = udf_rw32(sme->map) + lb_rel; 1567 *extres = ump->sparable_packet_len - lb_rel; 1568 return 0; 1569 } 1570 } 1571 1572 /* transform into its disc logical block */ 1573 part = ump->vtop[vpart]; 1574 pdesc = ump->partitions[part]; 1575 if (lb_num > udf_rw32(pdesc->part_len)) 1576 return EINVAL; 1577 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1578 1579 /* rest of block */ 1580 *extres = ump->sparable_packet_len - lb_rel; 1581 return 0; 1582 case UDF_VTOP_TYPE_META : 1583 default: 1584 printf("UDF vtop translation scheme %d unimplemented yet\n", 1585 ump->vtop_tp[vpart]); 1586 } 1587 1588 return EINVAL; 1589 } 1590 1591 /* --------------------------------------------------------------------- */ 1592 1593 /* To make absolutely sure we are NOT returning zero, add one :) */ 1594 1595 long 1596 udf_calchash(struct long_ad *icbptr) 1597 { 1598 /* ought to be enough since each mountpoint has its own chain */ 1599 return udf_rw32(icbptr->loc.lb_num) + 1; 1600 } 1601 1602 /* --------------------------------------------------------------------- */ 1603 1604 static struct udf_node * 1605 udf_hashget(struct udf_mount *ump, struct long_ad *icbptr) 1606 { 1607 struct udf_node *unp; 1608 struct vnode *vp; 1609 uint32_t hashline; 1610 1611 loop: 1612 simple_lock(&ump->ihash_slock); 1613 1614 hashline = udf_calchash(icbptr) & UDF_INODE_HASHMASK; 1615 LIST_FOREACH(unp, &ump->udf_nodes[hashline], hashchain) { 1616 assert(unp); 1617 if (unp->loc.loc.lb_num == icbptr->loc.lb_num && 1618 unp->loc.loc.part_num == icbptr->loc.part_num) { 1619 vp = unp->vnode; 1620 assert(vp); 1621 simple_lock(&vp->v_interlock); 1622 simple_unlock(&ump->ihash_slock); 1623 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) 1624 goto loop; 1625 return unp; 1626 } 1627 } 1628 simple_unlock(&ump->ihash_slock); 1629 1630 return NULL; 1631 } 1632 1633 /* --------------------------------------------------------------------- */ 1634 1635 static void 1636 udf_hashins(struct udf_node *unp) 1637 { 1638 struct udf_mount *ump; 1639 uint32_t hashline; 1640 1641 ump = unp->ump; 1642 simple_lock(&ump->ihash_slock); 1643 1644 hashline = udf_calchash(&unp->loc) & UDF_INODE_HASHMASK; 1645 LIST_INSERT_HEAD(&ump->udf_nodes[hashline], unp, hashchain); 1646 1647 simple_unlock(&ump->ihash_slock); 1648 } 1649 1650 /* --------------------------------------------------------------------- */ 1651 1652 static void 1653 udf_hashrem(struct udf_node *unp) 1654 { 1655 struct udf_mount *ump; 1656 1657 ump = unp->ump; 1658 simple_lock(&ump->ihash_slock); 1659 1660 LIST_REMOVE(unp, hashchain); 1661 1662 simple_unlock(&ump->ihash_slock); 1663 } 1664 1665 /* --------------------------------------------------------------------- */ 1666 1667 int 1668 udf_dispose_locked_node(struct udf_node *node) 1669 { 1670 if (!node) 1671 return 0; 1672 if (node->vnode) 1673 VOP_UNLOCK(node->vnode, 0); 1674 return udf_dispose_node(node); 1675 } 1676 1677 /* --------------------------------------------------------------------- */ 1678 1679 int 1680 udf_dispose_node(struct udf_node *node) 1681 { 1682 struct vnode *vp; 1683 1684 DPRINTF(NODE, ("udf_dispose_node called on node %p\n", node)); 1685 if (!node) { 1686 DPRINTF(NODE, ("UDF: Dispose node on node NULL, ignoring\n")); 1687 return 0; 1688 } 1689 1690 vp = node->vnode; 1691 1692 /* TODO extended attributes and streamdir */ 1693 1694 /* remove from our hash lookup table */ 1695 udf_hashrem(node); 1696 1697 /* dissociate our udf_node from the vnode */ 1698 vp->v_data = NULL; 1699 1700 /* free associated memory and the node itself */ 1701 if (node->fe) 1702 pool_put(node->ump->desc_pool, node->fe); 1703 if (node->efe) 1704 pool_put(node->ump->desc_pool, node->efe); 1705 pool_put(&udf_node_pool, node); 1706 1707 return 0; 1708 } 1709 1710 /* --------------------------------------------------------------------- */ 1711 1712 /* 1713 * Genfs interfacing 1714 * 1715 * static const struct genfs_ops udffs_genfsops = { 1716 * .gop_size = genfs_size, 1717 * size of transfers 1718 * .gop_alloc = udf_gop_alloc, 1719 * unknown 1720 * .gop_write = genfs_gop_write, 1721 * putpages interface code 1722 * .gop_markupdate = udf_gop_markupdate, 1723 * set update/modify flags etc. 1724 * } 1725 */ 1726 1727 /* 1728 * Genfs interface. These four functions are the only ones defined though not 1729 * documented... great.... why is chosen for the `.' initialisers i dont know 1730 * but other filingsystems seem to use it this way. 1731 */ 1732 1733 static int 1734 udf_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, 1735 kauth_cred_t cred) 1736 { 1737 return 0; 1738 } 1739 1740 1741 static void 1742 udf_gop_markupdate(struct vnode *vp, int flags) 1743 { 1744 struct udf_node *udf_node = VTOI(vp); 1745 u_long mask; 1746 1747 udf_node = udf_node; /* shut up gcc */ 1748 1749 mask = 0; 1750 #ifdef notyet 1751 if ((flags & GOP_UPDATE_ACCESSED) != 0) { 1752 mask = UDF_SET_ACCESS; 1753 } 1754 if ((flags & GOP_UPDATE_MODIFIED) != 0) { 1755 mask |= UDF_SET_UPDATE; 1756 } 1757 if (mask) { 1758 udf_node->update_flag |= mask; 1759 } 1760 #endif 1761 /* msdosfs doesn't do it, but shouldn't we update the times here? */ 1762 } 1763 1764 1765 static const struct genfs_ops udf_genfsops = { 1766 .gop_size = genfs_size, 1767 .gop_alloc = udf_gop_alloc, 1768 .gop_write = genfs_gop_write, 1769 .gop_markupdate = udf_gop_markupdate, 1770 }; 1771 1772 /* --------------------------------------------------------------------- */ 1773 1774 /* 1775 * Each node can have an attached streamdir node though not 1776 * recursively. These are otherwise known as named substreams/named 1777 * extended attributes that have no size limitations. 1778 * 1779 * `Normal' extended attributes are indicated with a number and are recorded 1780 * in either the fe/efe descriptor itself for small descriptors or recorded in 1781 * the attached extended attribute file. Since this file can get fragmented, 1782 * care ought to be taken. 1783 */ 1784 1785 int 1786 udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, 1787 struct udf_node **noderes) 1788 { 1789 union dscrptr *dscr, *tmpdscr; 1790 struct udf_node *node; 1791 struct vnode *nvp; 1792 struct long_ad icb_loc; 1793 extern int (**udf_vnodeop_p)(void *); 1794 uint64_t file_size; 1795 uint32_t lb_size, sector, dummy; 1796 int udf_file_type, dscr_type, strat, strat4096, needs_indirect; 1797 int error; 1798 1799 DPRINTF(NODE, ("udf_get_node called\n")); 1800 *noderes = node = NULL; 1801 1802 /* lock to disallow simultanious creation of same node */ 1803 lockmgr(&ump->get_node_lock, LK_EXCLUSIVE, NULL); 1804 1805 DPRINTF(NODE, ("\tlookup in hash table\n")); 1806 /* lookup in hash table */ 1807 assert(ump); 1808 assert(node_icb_loc); 1809 node = udf_hashget(ump, node_icb_loc); 1810 if (node) { 1811 DPRINTF(NODE, ("\tgot it from the hash!\n")); 1812 /* vnode is returned locked */ 1813 *noderes = node; 1814 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1815 return 0; 1816 } 1817 1818 /* garbage check: translate node_icb_loc to sectornr */ 1819 error = udf_translate_vtop(ump, node_icb_loc, §or, &dummy); 1820 if (error) { 1821 /* no use, this will fail anyway */ 1822 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1823 return EINVAL; 1824 } 1825 1826 /* build node (do initialise!) */ 1827 node = pool_get(&udf_node_pool, PR_WAITOK); 1828 memset(node, 0, sizeof(struct udf_node)); 1829 1830 DPRINTF(NODE, ("\tget new vnode\n")); 1831 /* give it a vnode */ 1832 error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, &nvp); 1833 if (error) { 1834 pool_put(&udf_node_pool, node); 1835 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1836 return error; 1837 } 1838 1839 /* allways return locked vnode */ 1840 if ((error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY))) { 1841 /* recycle vnode and unlock; simultanious will fail too */ 1842 ungetnewvnode(nvp); 1843 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1844 return error; 1845 } 1846 1847 /* initialise crosslinks, note location of fe/efe for hashing */ 1848 node->ump = ump; 1849 node->vnode = nvp; 1850 nvp->v_data = node; 1851 node->loc = *node_icb_loc; 1852 node->lockf = 0; 1853 1854 /* insert into the hash lookup */ 1855 udf_hashins(node); 1856 1857 /* safe to unlock, the entry is in the hash table, vnode is locked */ 1858 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1859 1860 icb_loc = *node_icb_loc; 1861 needs_indirect = 0; 1862 strat4096 = 0; 1863 udf_file_type = UDF_ICB_FILETYPE_UNKNOWN; 1864 file_size = 0; 1865 lb_size = udf_rw32(ump->logical_vol->lb_size); 1866 1867 do { 1868 error = udf_translate_vtop(ump, &icb_loc, §or, &dummy); 1869 if (error) 1870 break; 1871 1872 /* try to read in fe/efe */ 1873 error = udf_read_descriptor(ump, sector, M_UDFTEMP, &tmpdscr); 1874 1875 /* blank sector marks end of sequence, check this */ 1876 if ((tmpdscr == NULL) && (!strat4096)) 1877 error = ENOENT; 1878 1879 /* break if read error or blank sector */ 1880 if (error || (tmpdscr == NULL)) 1881 break; 1882 1883 /* process descriptor based on the descriptor type */ 1884 dscr_type = udf_rw16(tmpdscr->tag.id); 1885 1886 /* if dealing with an indirect entry, follow the link */ 1887 if (dscr_type == TAGID_INDIRECT_ENTRY) { 1888 needs_indirect = 0; 1889 icb_loc = tmpdscr->inde.indirect_icb; 1890 free(tmpdscr, M_UDFTEMP); 1891 continue; 1892 } 1893 1894 /* only file entries and extended file entries allowed here */ 1895 if ((dscr_type != TAGID_FENTRY) && 1896 (dscr_type != TAGID_EXTFENTRY)) { 1897 free(tmpdscr, M_UDFTEMP); 1898 error = ENOENT; 1899 break; 1900 } 1901 1902 /* get descriptor space from our pool */ 1903 KASSERT(udf_tagsize(tmpdscr, lb_size) == lb_size); 1904 1905 dscr = pool_get(ump->desc_pool, PR_WAITOK); 1906 memcpy(dscr, tmpdscr, lb_size); 1907 free(tmpdscr, M_UDFTEMP); 1908 1909 /* record and process/update (ext)fentry */ 1910 if (dscr_type == TAGID_FENTRY) { 1911 if (node->fe) 1912 pool_put(ump->desc_pool, node->fe); 1913 node->fe = &dscr->fe; 1914 strat = udf_rw16(node->fe->icbtag.strat_type); 1915 udf_file_type = node->fe->icbtag.file_type; 1916 file_size = udf_rw64(node->fe->inf_len); 1917 } else { 1918 if (node->efe) 1919 pool_put(ump->desc_pool, node->efe); 1920 node->efe = &dscr->efe; 1921 strat = udf_rw16(node->efe->icbtag.strat_type); 1922 udf_file_type = node->efe->icbtag.file_type; 1923 file_size = udf_rw64(node->efe->inf_len); 1924 } 1925 1926 /* check recording strategy (structure) */ 1927 1928 /* 1929 * Strategy 4096 is a daisy linked chain terminating with an 1930 * unrecorded sector or a TERM descriptor. The next 1931 * descriptor is to be found in the sector that follows the 1932 * current sector. 1933 */ 1934 if (strat == 4096) { 1935 strat4096 = 1; 1936 needs_indirect = 1; 1937 1938 icb_loc.loc.lb_num = udf_rw32(icb_loc.loc.lb_num) + 1; 1939 } 1940 1941 /* 1942 * Strategy 4 is the normal strategy and terminates, but if 1943 * we're in strategy 4096, we can't have strategy 4 mixed in 1944 */ 1945 1946 if (strat == 4) { 1947 if (strat4096) { 1948 error = EINVAL; 1949 break; 1950 } 1951 break; /* done */ 1952 } 1953 } while (!error); 1954 1955 if (error) { 1956 /* recycle udf_node */ 1957 udf_dispose_node(node); 1958 1959 /* recycle vnode */ 1960 nvp->v_data = NULL; 1961 ungetnewvnode(nvp); 1962 1963 return EINVAL; /* error code ok? */ 1964 } 1965 1966 /* post process and initialise node */ 1967 1968 /* assert no references to dscr anymore beyong this point */ 1969 assert((node->fe) || (node->efe)); 1970 dscr = NULL; 1971 1972 /* 1973 * Record where to record an updated version of the descriptor. If 1974 * there is a sequence of indirect entries, icb_loc will have been 1975 * updated. Its the write disipline to allocate new space and to make 1976 * sure the chain is maintained. 1977 * 1978 * `needs_indirect' flags if the next location is to be filled with 1979 * with an indirect entry. 1980 */ 1981 node->next_loc = icb_loc; 1982 node->needs_indirect = needs_indirect; 1983 1984 /* 1985 * Translate UDF filetypes into vnode types. 1986 * 1987 * Systemfiles like the meta main and mirror files are not treated as 1988 * normal files, so we type them as having no type. UDF dictates that 1989 * they are not allowed to be visible. 1990 */ 1991 1992 /* TODO specfs, fifofs etc etc. vnops setting */ 1993 switch (udf_file_type) { 1994 case UDF_ICB_FILETYPE_DIRECTORY : 1995 case UDF_ICB_FILETYPE_STREAMDIR : 1996 nvp->v_type = VDIR; 1997 break; 1998 case UDF_ICB_FILETYPE_BLOCKDEVICE : 1999 nvp->v_type = VBLK; 2000 break; 2001 case UDF_ICB_FILETYPE_CHARDEVICE : 2002 nvp->v_type = VCHR; 2003 break; 2004 case UDF_ICB_FILETYPE_SYMLINK : 2005 nvp->v_type = VLNK; 2006 break; 2007 case UDF_ICB_FILETYPE_META_MAIN : 2008 case UDF_ICB_FILETYPE_META_MIRROR : 2009 nvp->v_type = VNON; 2010 break; 2011 case UDF_ICB_FILETYPE_RANDOMACCESS : 2012 nvp->v_type = VREG; 2013 break; 2014 default: 2015 /* YIKES, either a block/char device, fifo or something else */ 2016 nvp->v_type = VNON; 2017 } 2018 2019 /* initialise genfs */ 2020 genfs_node_init(nvp, &udf_genfsops); 2021 2022 /* don't forget to set vnode's v_size */ 2023 nvp->v_size = file_size; 2024 2025 /* TODO ext attr and streamdir nodes */ 2026 2027 *noderes = node; 2028 2029 return 0; 2030 } 2031 2032 /* --------------------------------------------------------------------- */ 2033 2034 /* UDF<->unix converters */ 2035 2036 /* --------------------------------------------------------------------- */ 2037 2038 static mode_t 2039 udf_perm_to_unix_mode(uint32_t perm) 2040 { 2041 mode_t mode; 2042 2043 mode = ((perm & UDF_FENTRY_PERM_USER_MASK) ); 2044 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK ) >> 2); 2045 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 2046 2047 return mode; 2048 } 2049 2050 /* --------------------------------------------------------------------- */ 2051 2052 #ifdef notyet 2053 static uint32_t 2054 unix_mode_to_udf_perm(mode_t mode) 2055 { 2056 uint32_t perm; 2057 2058 perm = ((mode & S_IRWXO) ); 2059 perm |= ((mode & S_IRWXG) << 2); 2060 perm |= ((mode & S_IRWXU) << 4); 2061 perm |= ((mode & S_IWOTH) << 3); 2062 perm |= ((mode & S_IWGRP) << 5); 2063 perm |= ((mode & S_IWUSR) << 7); 2064 2065 return perm; 2066 } 2067 #endif 2068 2069 /* --------------------------------------------------------------------- */ 2070 2071 static uint32_t 2072 udf_icb_to_unix_filetype(uint32_t icbftype) 2073 { 2074 switch (icbftype) { 2075 case UDF_ICB_FILETYPE_DIRECTORY : 2076 case UDF_ICB_FILETYPE_STREAMDIR : 2077 return S_IFDIR; 2078 case UDF_ICB_FILETYPE_FIFO : 2079 return S_IFIFO; 2080 case UDF_ICB_FILETYPE_CHARDEVICE : 2081 return S_IFCHR; 2082 case UDF_ICB_FILETYPE_BLOCKDEVICE : 2083 return S_IFBLK; 2084 case UDF_ICB_FILETYPE_RANDOMACCESS : 2085 return S_IFREG; 2086 case UDF_ICB_FILETYPE_SYMLINK : 2087 return S_IFLNK; 2088 case UDF_ICB_FILETYPE_SOCKET : 2089 return S_IFSOCK; 2090 } 2091 /* no idea what this is */ 2092 return 0; 2093 } 2094 2095 /* --------------------------------------------------------------------- */ 2096 2097 /* TODO KNF-ify */ 2098 2099 void 2100 udf_to_unix_name(char *result, char *id, int len, struct charspec *chsp) 2101 { 2102 uint16_t *raw_name, *unix_name; 2103 uint16_t *inchp, ch; 2104 uint8_t *outchp; 2105 int ucode_chars, nice_uchars; 2106 2107 raw_name = malloc(2048 * sizeof(uint16_t), M_UDFTEMP, M_WAITOK); 2108 unix_name = raw_name + 1024; /* split space in half */ 2109 assert(sizeof(char) == sizeof(uint8_t)); 2110 outchp = (uint8_t *) result; 2111 if ((chsp->type == 0) && (strcmp((char*) chsp->inf, "OSTA Compressed Unicode") == 0)) { 2112 *raw_name = *unix_name = 0; 2113 ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name); 2114 ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name)); 2115 nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars); 2116 for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) { 2117 ch = *inchp; 2118 /* XXX sloppy unicode -> latin */ 2119 *outchp++ = ch & 255; 2120 if (!ch) break; 2121 } 2122 *outchp++ = 0; 2123 } else { 2124 /* assume 8bit char length byte latin-1 */ 2125 assert(*id == 8); 2126 strncpy((char *) result, (char *) (id+1), strlen((char *) (id+1))); 2127 } 2128 free(raw_name, M_UDFTEMP); 2129 } 2130 2131 /* --------------------------------------------------------------------- */ 2132 2133 /* TODO KNF-ify */ 2134 2135 void 2136 unix_to_udf_name(char *result, char *name, 2137 uint8_t *result_len, struct charspec *chsp) 2138 { 2139 uint16_t *raw_name; 2140 int udf_chars, name_len; 2141 char *inchp; 2142 uint16_t *outchp; 2143 2144 raw_name = malloc(1024, M_UDFTEMP, M_WAITOK); 2145 /* convert latin-1 or whatever to unicode-16 */ 2146 *raw_name = 0; 2147 name_len = 0; 2148 inchp = name; 2149 outchp = raw_name; 2150 while (*inchp) { 2151 *outchp++ = (uint16_t) (*inchp++); 2152 name_len++; 2153 } 2154 2155 if ((chsp->type == 0) && (strcmp((char *) chsp->inf, "OSTA Compressed Unicode") == 0)) { 2156 udf_chars = udf_CompressUnicode(name_len, 8, (unicode_t *) raw_name, (byte *) result); 2157 } else { 2158 /* XXX assume 8bit char length byte latin-1 */ 2159 *result++ = 8; udf_chars = 1; 2160 strncpy(result, name + 1, strlen(name+1)); 2161 udf_chars += strlen(name); 2162 } 2163 *result_len = udf_chars; 2164 free(raw_name, M_UDFTEMP); 2165 } 2166 2167 /* --------------------------------------------------------------------- */ 2168 2169 /* 2170 * Timestamp to timespec conversion code is taken with small modifications 2171 * from FreeBSDs /sys/fs/udf by Scott Long <scottl@freebsd.org>. Added with 2172 * permission from Scott. 2173 */ 2174 2175 static int mon_lens[2][12] = { 2176 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 2177 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 2178 }; 2179 2180 2181 static int 2182 udf_isaleapyear(int year) 2183 { 2184 int i; 2185 2186 i = (year % 4) ? 0 : 1; 2187 i &= (year % 100) ? 1 : 0; 2188 i |= (year % 400) ? 0 : 1; 2189 2190 return i; 2191 } 2192 2193 2194 void 2195 udf_timestamp_to_timespec(struct udf_mount *ump, 2196 struct timestamp *timestamp, 2197 struct timespec *timespec) 2198 { 2199 uint32_t usecs, secs, nsecs; 2200 uint16_t tz; 2201 int i, lpyear, daysinyear, year; 2202 2203 timespec->tv_sec = secs = 0; 2204 timespec->tv_nsec = nsecs = 0; 2205 2206 /* 2207 * DirectCD seems to like using bogus year values. 2208 * 2209 * Distrust time->month especially, since it will be used for an array 2210 * index. 2211 */ 2212 year = udf_rw16(timestamp->year); 2213 if ((year < 1970) || (timestamp->month > 12)) { 2214 return; 2215 } 2216 2217 /* Calculate the time and day 2218 * Day is 1-31, Month is 1-12 2219 */ 2220 2221 usecs = timestamp->usec + 2222 100*timestamp->hund_usec + 10000*timestamp->centisec; 2223 nsecs = usecs * 1000; 2224 secs = timestamp->second; 2225 secs += timestamp->minute * 60; 2226 secs += timestamp->hour * 3600; 2227 secs += (timestamp->day-1) * 3600 * 24; 2228 2229 /* Calclulate the month */ 2230 lpyear = udf_isaleapyear(year); 2231 for (i = 1; i < timestamp->month; i++) 2232 secs += mon_lens[lpyear][i-1] * 3600 * 24; 2233 2234 for (i = 1970; i < year; i++) { 2235 daysinyear = udf_isaleapyear(i) + 365 ; 2236 secs += daysinyear * 3600 * 24; 2237 } 2238 2239 /* 2240 * Calculate the time zone. The timezone is 12 bit signed 2's 2241 * compliment, so we gotta do some extra magic to handle it right. 2242 */ 2243 tz = udf_rw16(timestamp->type_tz); 2244 tz &= 0x0fff; /* only lower 12 bits are significant */ 2245 if (tz & 0x0800) /* sign extention */ 2246 tz |= 0xf000; 2247 2248 /* TODO check timezone conversion */ 2249 /* check if we are specified a timezone to convert */ 2250 if (udf_rw16(timestamp->type_tz) & 0x1000) { 2251 if ((int16_t) tz != -2047) 2252 secs -= (int16_t) tz * 60; 2253 } else { 2254 secs -= ump->mount_args.gmtoff; 2255 } 2256 2257 timespec->tv_sec = secs; 2258 timespec->tv_nsec = nsecs; 2259 } 2260 2261 /* --------------------------------------------------------------------- */ 2262 2263 /* 2264 * Attribute and filetypes converters with get/set pairs 2265 */ 2266 2267 uint32_t 2268 udf_getaccessmode(struct udf_node *udf_node) 2269 { 2270 struct file_entry *fe; 2271 struct extfile_entry *efe; 2272 uint32_t udf_perm, icbftype; 2273 uint32_t mode, ftype; 2274 uint16_t icbflags; 2275 2276 if (udf_node->fe) { 2277 fe = udf_node->fe; 2278 udf_perm = udf_rw32(fe->perm); 2279 icbftype = fe->icbtag.file_type; 2280 icbflags = udf_rw16(fe->icbtag.flags); 2281 } else { 2282 assert(udf_node->efe); 2283 efe = udf_node->efe; 2284 udf_perm = udf_rw32(efe->perm); 2285 icbftype = efe->icbtag.file_type; 2286 icbflags = udf_rw16(efe->icbtag.flags); 2287 } 2288 2289 mode = udf_perm_to_unix_mode(udf_perm); 2290 ftype = udf_icb_to_unix_filetype(icbftype); 2291 2292 /* set suid, sgid, sticky from flags in fe/efe */ 2293 if (icbflags & UDF_ICB_TAG_FLAGS_SETUID) 2294 mode |= S_ISUID; 2295 if (icbflags & UDF_ICB_TAG_FLAGS_SETGID) 2296 mode |= S_ISGID; 2297 if (icbflags & UDF_ICB_TAG_FLAGS_STICKY) 2298 mode |= S_ISVTX; 2299 2300 return mode | ftype; 2301 } 2302 2303 /* --------------------------------------------------------------------- */ 2304 2305 /* 2306 * Directory read and manipulation functions 2307 */ 2308 2309 int 2310 udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, 2311 struct long_ad *icb_loc) 2312 { 2313 struct udf_node *dir_node = VTOI(vp); 2314 struct file_entry *fe; 2315 struct extfile_entry *efe; 2316 struct fileid_desc *fid; 2317 struct dirent dirent; 2318 uint64_t file_size, diroffset; 2319 uint32_t lb_size; 2320 int found, error; 2321 2322 /* get directory filesize */ 2323 if (dir_node->fe) { 2324 fe = dir_node->fe; 2325 file_size = udf_rw64(fe->inf_len); 2326 } else { 2327 assert(dir_node->efe); 2328 efe = dir_node->efe; 2329 file_size = udf_rw64(efe->inf_len); 2330 } 2331 2332 /* allocate temporary space for fid */ 2333 lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 2334 fid = malloc(lb_size, M_TEMP, M_WAITOK); 2335 2336 found = 0; 2337 diroffset = 0; 2338 while (!found && (diroffset < file_size)) { 2339 /* transfer a new fid/dirent */ 2340 error = udf_read_fid_stream(vp, &diroffset, fid, &dirent); 2341 if (error) 2342 break; 2343 2344 /* skip deleted entries */ 2345 if (fid->file_char & UDF_FILE_CHAR_DEL) 2346 continue; 2347 2348 if ((strlen(dirent.d_name) == namelen) && 2349 (strncmp(dirent.d_name, name, namelen) == 0)) { 2350 found = 1; 2351 *icb_loc = fid->icb; 2352 } 2353 } 2354 free(fid, M_TEMP); 2355 2356 return found; 2357 } 2358 2359 /* --------------------------------------------------------------------- */ 2360 2361 /* 2362 * Read one fid and process it into a dirent and advance to the next (*fid) 2363 * has to be allocated a logical block in size, (*dirent) struct dirent length 2364 */ 2365 2366 int 2367 udf_read_fid_stream(struct vnode *vp, uint64_t *offset, 2368 struct fileid_desc *fid, struct dirent *dirent) 2369 { 2370 struct udf_node *dir_node = VTOI(vp); 2371 struct udf_mount *ump = dir_node->ump; 2372 struct file_entry *fe; 2373 struct extfile_entry *efe; 2374 struct uio dir_uio; 2375 struct iovec dir_iovec; 2376 uint32_t entry_length, lb_size; 2377 uint64_t file_size; 2378 char *fid_name; 2379 int enough, error; 2380 2381 assert(fid); 2382 assert(dirent); 2383 assert(dir_node); 2384 assert(offset); 2385 assert(*offset != 1); 2386 2387 DPRINTF(FIDS, ("read_fid_stream called\n")); 2388 /* check if we're past the end of the directory */ 2389 if (dir_node->fe) { 2390 fe = dir_node->fe; 2391 file_size = udf_rw64(fe->inf_len); 2392 } else { 2393 assert(dir_node->efe); 2394 efe = dir_node->efe; 2395 file_size = udf_rw64(efe->inf_len); 2396 } 2397 if (*offset >= file_size) 2398 return EINVAL; 2399 2400 /* get maximum length of FID descriptor */ 2401 lb_size = udf_rw32(ump->logical_vol->lb_size); 2402 2403 /* initialise return values */ 2404 entry_length = 0; 2405 memset(dirent, 0, sizeof(struct dirent)); 2406 memset(fid, 0, lb_size); 2407 2408 /* TODO use vn_rdwr instead of creating our own uio */ 2409 /* read part of the directory */ 2410 memset(&dir_uio, 0, sizeof(struct uio)); 2411 dir_uio.uio_rw = UIO_READ; /* read into this space */ 2412 dir_uio.uio_iovcnt = 1; 2413 dir_uio.uio_iov = &dir_iovec; 2414 UIO_SETUP_SYSSPACE(&dir_uio); 2415 dir_iovec.iov_base = fid; 2416 dir_iovec.iov_len = lb_size; 2417 dir_uio.uio_offset = *offset; 2418 2419 /* limit length of read in piece */ 2420 dir_uio.uio_resid = MIN(file_size - (*offset), lb_size); 2421 2422 /* read the part into the fid space */ 2423 error = VOP_READ(vp, &dir_uio, IO_ALTSEMANTICS, NOCRED); 2424 if (error) 2425 return error; 2426 2427 /* 2428 * Check if we got a whole descriptor. 2429 * XXX Try to `resync' directory stream when something is very wrong. 2430 * 2431 */ 2432 enough = (dir_uio.uio_offset - (*offset) >= UDF_FID_SIZE); 2433 if (!enough) { 2434 /* short dir ... */ 2435 return EIO; 2436 } 2437 2438 /* check if our FID header is OK */ 2439 error = udf_check_tag(fid); 2440 DPRINTFIF(FIDS, error, ("read fids: tag check failed\n")); 2441 if (!error) { 2442 if (udf_rw16(fid->tag.id) != TAGID_FID) 2443 error = ENOENT; 2444 } 2445 DPRINTFIF(FIDS, !error, ("\ttag checked ok: got TAGID_FID\n")); 2446 2447 /* check for length */ 2448 if (!error) { 2449 entry_length = udf_fidsize(fid, lb_size); 2450 enough = (dir_uio.uio_offset - (*offset) >= entry_length); 2451 } 2452 DPRINTFIF(FIDS, !error, ("\tentry_length = %d, enough = %s\n", 2453 entry_length, enough?"yes":"no")); 2454 2455 if (!enough) { 2456 /* short dir ... bomb out */ 2457 return EIO; 2458 } 2459 2460 /* check FID contents */ 2461 if (!error) { 2462 error = udf_check_tag_payload((union dscrptr *) fid, lb_size); 2463 DPRINTF(FIDS, ("\tpayload checked ok\n")); 2464 } 2465 if (error) { 2466 /* note that is sometimes a bit quick to report */ 2467 printf("BROKEN DIRECTORY ENTRY\n"); 2468 /* RESYNC? */ 2469 /* TODO: use udf_resync_fid_stream */ 2470 return EIO; 2471 } 2472 DPRINTF(FIDS, ("\tinterpret FID\n")); 2473 2474 /* we got a whole and valid descriptor! */ 2475 2476 /* create resulting dirent structure */ 2477 fid_name = (char *) fid->data + udf_rw16(fid->l_iu); 2478 udf_to_unix_name(dirent->d_name, 2479 fid_name, fid->l_fi, &ump->logical_vol->desc_charset); 2480 2481 /* '..' has no name, so provide one */ 2482 if (fid->file_char & UDF_FILE_CHAR_PAR) 2483 strcpy(dirent->d_name, ".."); 2484 2485 dirent->d_fileno = udf_calchash(&fid->icb); /* inode hash XXX */ 2486 dirent->d_namlen = strlen(dirent->d_name); 2487 dirent->d_reclen = _DIRENT_SIZE(dirent); 2488 2489 /* 2490 * Note that its not worth trying to go for the filetypes now... its 2491 * too expensive too 2492 */ 2493 dirent->d_type = DT_UNKNOWN; 2494 2495 /* initial guess for filetype we can make */ 2496 if (fid->file_char & UDF_FILE_CHAR_DIR) 2497 dirent->d_type = DT_DIR; 2498 2499 /* advance */ 2500 *offset += entry_length; 2501 2502 return error; 2503 } 2504 2505 /* --------------------------------------------------------------------- */ 2506 2507 /* 2508 * block based file reading and writing 2509 */ 2510 2511 static int 2512 udf_read_internal(struct udf_node *node, uint8_t *blob) 2513 { 2514 struct udf_mount *ump; 2515 struct file_entry *fe; 2516 struct extfile_entry *efe; 2517 uint64_t inflen; 2518 uint32_t sector_size; 2519 uint8_t *pos; 2520 int icbflags, addr_type; 2521 2522 /* shut up gcc */ 2523 inflen = addr_type = icbflags = 0; 2524 pos = NULL; 2525 2526 /* get extent and do some paranoia checks */ 2527 ump = node->ump; 2528 sector_size = ump->discinfo.sector_size; 2529 2530 fe = node->fe; 2531 efe = node->efe; 2532 if (fe) { 2533 inflen = udf_rw64(fe->inf_len); 2534 pos = &fe->data[0] + udf_rw32(fe->l_ea); 2535 icbflags = udf_rw16(fe->icbtag.flags); 2536 } 2537 if (efe) { 2538 inflen = udf_rw64(efe->inf_len); 2539 pos = &efe->data[0] + udf_rw32(efe->l_ea); 2540 icbflags = udf_rw16(efe->icbtag.flags); 2541 } 2542 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2543 2544 assert(addr_type == UDF_ICB_INTERN_ALLOC); 2545 assert(inflen < sector_size); 2546 2547 /* copy out info */ 2548 memset(blob, 0, sector_size); 2549 memcpy(blob, pos, inflen); 2550 2551 return 0; 2552 } 2553 2554 /* --------------------------------------------------------------------- */ 2555 2556 /* 2557 * Read file extent reads an extent specified in sectors from the file. It is 2558 * sector based; i.e. no `fancy' offsets. 2559 */ 2560 2561 int 2562 udf_read_file_extent(struct udf_node *node, 2563 uint32_t from, uint32_t sectors, 2564 uint8_t *blob) 2565 { 2566 struct buf buf; 2567 uint32_t sector_size; 2568 2569 BUF_INIT(&buf); 2570 2571 sector_size = node->ump->discinfo.sector_size; 2572 2573 buf.b_bufsize = sectors * sector_size; 2574 buf.b_data = blob; 2575 buf.b_bcount = buf.b_bufsize; 2576 buf.b_resid = buf.b_bcount; 2577 buf.b_flags = B_BUSY | B_READ; 2578 buf.b_vp = node->vnode; 2579 buf.b_proc = NULL; 2580 2581 buf.b_blkno = from; 2582 buf.b_lblkno = 0; 2583 BIO_SETPRIO(&buf, BPRIO_TIMELIMITED); 2584 2585 udf_read_filebuf(node, &buf); 2586 return biowait(&buf); 2587 } 2588 2589 2590 /* --------------------------------------------------------------------- */ 2591 2592 /* 2593 * Read file extent in the buffer. 2594 * 2595 * The splitup of the extent into seperate request-buffers is to minimise 2596 * copying around as much as possible. 2597 */ 2598 2599 2600 /* maximum of 128 translations (!) (64 kb in 512 byte sectors) */ 2601 #define FILEBUFSECT 128 2602 2603 void 2604 udf_read_filebuf(struct udf_node *node, struct buf *buf) 2605 { 2606 struct buf *nestbuf; 2607 uint64_t *mapping; 2608 uint64_t run_start; 2609 uint32_t sector_size; 2610 uint32_t buf_offset, sector, rbuflen, rblk; 2611 uint8_t *buf_pos; 2612 int error, run_length; 2613 2614 uint32_t from; 2615 uint32_t sectors; 2616 2617 sector_size = node->ump->discinfo.sector_size; 2618 2619 from = buf->b_blkno; 2620 sectors = buf->b_bcount / sector_size; 2621 2622 /* assure we have enough translation slots */ 2623 KASSERT(buf->b_bcount / sector_size <= FILEBUFSECT); 2624 KASSERT(MAXPHYS / sector_size <= FILEBUFSECT); 2625 2626 if (sectors > FILEBUFSECT) { 2627 printf("udf_read_filebuf: implementation limit on bufsize\n"); 2628 buf->b_error = EIO; 2629 buf->b_flags |= B_ERROR; 2630 biodone(buf); 2631 return; 2632 } 2633 2634 mapping = malloc(sizeof(*mapping) * FILEBUFSECT, M_TEMP, M_WAITOK); 2635 2636 error = 0; 2637 DPRINTF(READ, ("\ttranslate %d-%d\n", from, sectors)); 2638 error = udf_translate_file_extent(node, from, sectors, mapping); 2639 if (error) { 2640 buf->b_error = error; 2641 buf->b_flags |= B_ERROR; 2642 biodone(buf); 2643 goto out; 2644 } 2645 DPRINTF(READ, ("\ttranslate extent went OK\n")); 2646 2647 /* pre-check if internal or parts are zero */ 2648 if (*mapping == UDF_TRANS_INTERN) { 2649 error = udf_read_internal(node, (uint8_t *) buf->b_data); 2650 if (error) { 2651 buf->b_error = error; 2652 buf->b_flags |= B_ERROR; 2653 } 2654 biodone(buf); 2655 goto out; 2656 } 2657 DPRINTF(READ, ("\tnot intern\n")); 2658 2659 /* request read-in of data from disc sheduler */ 2660 buf->b_resid = buf->b_bcount; 2661 for (sector = 0; sector < sectors; sector++) { 2662 buf_offset = sector * sector_size; 2663 buf_pos = (uint8_t *) buf->b_data + buf_offset; 2664 DPRINTF(READ, ("\tprocessing rel sector %d\n", sector)); 2665 2666 switch (mapping[sector]) { 2667 case UDF_TRANS_UNMAPPED: 2668 case UDF_TRANS_ZERO: 2669 /* copy zero sector */ 2670 memset(buf_pos, 0, sector_size); 2671 DPRINTF(READ, ("\treturning zero sector\n")); 2672 nestiobuf_done(buf, sector_size, 0); 2673 break; 2674 default : 2675 DPRINTF(READ, ("\tread sector " 2676 "%"PRIu64"\n", mapping[sector])); 2677 2678 run_start = mapping[sector]; 2679 run_length = 1; 2680 while (sector < sectors-1) { 2681 if (mapping[sector+1] != mapping[sector]+1) 2682 break; 2683 run_length++; 2684 sector++; 2685 } 2686 2687 /* 2688 * nest an iobuf and mark it for async reading. Since 2689 * we're using nested buffers, they can't be cached by 2690 * design. 2691 */ 2692 rbuflen = run_length * sector_size; 2693 rblk = run_start * (sector_size/DEV_BSIZE); 2694 2695 nestbuf = getiobuf(); 2696 nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen); 2697 /* nestbuf is B_ASYNC */ 2698 2699 /* CD shedules on raw blkno */ 2700 nestbuf->b_blkno = rblk; 2701 nestbuf->b_proc = NULL; 2702 nestbuf->b_cylinder = 0; 2703 nestbuf->b_rawblkno = rblk; 2704 VOP_STRATEGY(node->ump->devvp, nestbuf); 2705 } 2706 } 2707 out: 2708 DPRINTF(READ, ("\tend of read_filebuf\n")); 2709 free(mapping, M_TEMP); 2710 return; 2711 } 2712 #undef FILEBUFSECT 2713 2714 2715 /* --------------------------------------------------------------------- */ 2716 2717 /* 2718 * Translate an extent (in sectors) into sector numbers; used for read and 2719 * write operations. DOESNT't check extents. 2720 */ 2721 2722 int 2723 udf_translate_file_extent(struct udf_node *node, 2724 uint32_t from, uint32_t pages, 2725 uint64_t *map) 2726 { 2727 struct udf_mount *ump; 2728 struct file_entry *fe; 2729 struct extfile_entry *efe; 2730 struct short_ad *s_ad; 2731 struct long_ad *l_ad, t_ad; 2732 uint64_t transsec; 2733 uint32_t sector_size, transsec32; 2734 uint32_t overlap, translen; 2735 uint32_t vpart_num, lb_num, len, alloclen; 2736 uint8_t *pos; 2737 int error, flags, addr_type, icblen, icbflags; 2738 2739 if (!node) 2740 return ENOENT; 2741 2742 /* shut up gcc */ 2743 alloclen = addr_type = icbflags = 0; 2744 pos = NULL; 2745 2746 /* do the work */ 2747 ump = node->ump; 2748 sector_size = ump->discinfo.sector_size; 2749 fe = node->fe; 2750 efe = node->efe; 2751 if (fe) { 2752 alloclen = udf_rw32(fe->l_ad); 2753 pos = &fe->data[0] + udf_rw32(fe->l_ea); 2754 icbflags = udf_rw16(fe->icbtag.flags); 2755 } 2756 if (efe) { 2757 alloclen = udf_rw32(efe->l_ad); 2758 pos = &efe->data[0] + udf_rw32(efe->l_ea); 2759 icbflags = udf_rw16(efe->icbtag.flags); 2760 } 2761 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2762 2763 DPRINTF(TRANSLATE, ("udf trans: alloc_len = %d, addr_type %d, " 2764 "fe %p, efe %p\n", alloclen, addr_type, fe, efe)); 2765 2766 vpart_num = udf_rw16(node->loc.loc.part_num); 2767 lb_num = len = icblen = 0; /* shut up gcc */ 2768 while (pages && alloclen) { 2769 DPRINTF(TRANSLATE, ("\taddr_type %d\n", addr_type)); 2770 switch (addr_type) { 2771 case UDF_ICB_INTERN_ALLOC : 2772 /* TODO check extents? */ 2773 *map = UDF_TRANS_INTERN; 2774 return 0; 2775 case UDF_ICB_SHORT_ALLOC : 2776 icblen = sizeof(struct short_ad); 2777 s_ad = (struct short_ad *) pos; 2778 len = udf_rw32(s_ad->len); 2779 lb_num = udf_rw32(s_ad->lb_num); 2780 break; 2781 case UDF_ICB_LONG_ALLOC : 2782 icblen = sizeof(struct long_ad); 2783 l_ad = (struct long_ad *) pos; 2784 len = udf_rw32(l_ad->len); 2785 lb_num = udf_rw32(l_ad->loc.lb_num); 2786 vpart_num = udf_rw16(l_ad->loc.part_num); 2787 DPRINTFIF(TRANSLATE, 2788 (l_ad->impl.im_used.flags & 2789 UDF_ADIMP_FLAGS_EXTENT_ERASED), 2790 ("UDF: got an `extent erased' flag in long_ad\n")); 2791 break; 2792 default: 2793 /* can't be here */ 2794 return EINVAL; /* for sure */ 2795 } 2796 2797 /* process extent */ 2798 flags = UDF_EXT_FLAGS(len); 2799 len = UDF_EXT_LEN(len); 2800 2801 overlap = (len + sector_size -1) / sector_size; 2802 if (from) { 2803 if (from > overlap) { 2804 from -= overlap; 2805 overlap = 0; 2806 } else { 2807 lb_num += from; /* advance in extent */ 2808 overlap -= from; 2809 from = 0; 2810 } 2811 } 2812 2813 overlap = MIN(overlap, pages); 2814 while (overlap) { 2815 switch (flags) { 2816 case UDF_EXT_REDIRECT : 2817 /* no support for allocation extentions yet */ 2818 /* TODO support for allocation extention */ 2819 return ENOENT; 2820 case UDF_EXT_FREED : 2821 case UDF_EXT_FREE : 2822 transsec = UDF_TRANS_ZERO; 2823 translen = overlap; 2824 while (overlap && pages && translen) { 2825 *map++ = transsec; 2826 overlap--; pages--; translen--; 2827 } 2828 break; 2829 case UDF_EXT_ALLOCATED : 2830 t_ad.loc.lb_num = udf_rw32(lb_num); 2831 t_ad.loc.part_num = udf_rw16(vpart_num); 2832 error = udf_translate_vtop(ump, 2833 &t_ad, &transsec32, &translen); 2834 transsec = transsec32; 2835 if (error) 2836 return error; 2837 while (overlap && pages && translen) { 2838 *map++ = transsec; 2839 transsec++; 2840 overlap--; pages--; translen--; 2841 } 2842 break; 2843 } 2844 } 2845 pos += icblen; 2846 alloclen -= icblen; 2847 } 2848 return 0; 2849 } 2850 2851 /* --------------------------------------------------------------------- */ 2852 2853