1 /* $NetBSD: udf_subr.c,v 1.22 2006/10/12 01:32:14 christos 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.22 2006/10/12 01:32:14 christos 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 __unused) 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 free(dscr, M_UDFVOLD); 756 return EINVAL; 757 } 758 759 UDF_UPDATE_DSCR(ump->partitions[partnr], &dscr->pd); 760 break; 761 case TAGID_VOL : /* volume space extender; rare */ 762 DPRINTF(VOLUMES, ("VDS extender ignored\n")); 763 free(dscr, M_UDFVOLD); 764 break; 765 default : 766 DPRINTF(VOLUMES, ("Unhandled VDS type %d\n", 767 udf_rw16(dscr->tag.id))); 768 free(dscr, M_UDFVOLD); 769 } 770 771 return 0; 772 } 773 #undef UDF_UPDATE_DSCR 774 775 /* --------------------------------------------------------------------- */ 776 777 static int 778 udf_read_vds_extent(struct udf_mount *ump, uint32_t loc, uint32_t len) 779 { 780 union dscrptr *dscr; 781 uint32_t sector_size, dscr_size; 782 int error; 783 784 sector_size = ump->discinfo.sector_size; 785 786 /* loc is sectornr, len is in bytes */ 787 error = EIO; 788 while (len) { 789 error = udf_read_descriptor(ump, loc, M_UDFVOLD, &dscr); 790 if (error) 791 return error; 792 793 /* blank block is a terminator */ 794 if (dscr == NULL) 795 return 0; 796 797 /* TERM descriptor is a terminator */ 798 if (udf_rw16(dscr->tag.id) == TAGID_TERM) { 799 free(dscr, M_UDFVOLD); 800 return 0; 801 } 802 803 /* process all others */ 804 dscr_size = udf_tagsize(dscr, sector_size); 805 error = udf_process_vds_descriptor(ump, dscr); 806 if (error) { 807 free(dscr, M_UDFVOLD); 808 break; 809 } 810 assert((dscr_size % sector_size) == 0); 811 812 len -= dscr_size; 813 loc += dscr_size / sector_size; 814 } 815 816 return error; 817 } 818 819 820 int 821 udf_read_vds_space(struct udf_mount *ump) 822 { 823 struct anchor_vdp *anchor, *anchor2; 824 size_t size; 825 uint32_t main_loc, main_len; 826 uint32_t reserve_loc, reserve_len; 827 int error; 828 829 /* 830 * read in VDS space provided by the anchors; if one descriptor read 831 * fails, try the mirror sector. 832 * 833 * check if 2nd anchor is different from 1st; if so, go for 2nd. This 834 * avoids the `compatibility features' of DirectCD that may confuse 835 * stuff completely. 836 */ 837 838 anchor = ump->anchors[0]; 839 anchor2 = ump->anchors[1]; 840 assert(anchor); 841 842 if (anchor2) { 843 size = sizeof(struct extent_ad); 844 if (memcmp(&anchor->main_vds_ex, &anchor2->main_vds_ex, size)) 845 anchor = anchor2; 846 /* reserve is specified to be a literal copy of main */ 847 } 848 849 main_loc = udf_rw32(anchor->main_vds_ex.loc); 850 main_len = udf_rw32(anchor->main_vds_ex.len); 851 852 reserve_loc = udf_rw32(anchor->reserve_vds_ex.loc); 853 reserve_len = udf_rw32(anchor->reserve_vds_ex.len); 854 855 error = udf_read_vds_extent(ump, main_loc, main_len); 856 if (error) { 857 printf("UDF mount: reading in reserve VDS extent\n"); 858 error = udf_read_vds_extent(ump, reserve_loc, reserve_len); 859 } 860 861 return error; 862 } 863 864 /* --------------------------------------------------------------------- */ 865 866 /* 867 * Read in the logical volume integrity sequence pointed to by our logical 868 * volume descriptor. Its a sequence that can be extended using fields in the 869 * integrity descriptor itself. On sequential media only one is found, on 870 * rewritable media a sequence of descriptors can be found as a form of 871 * history keeping and on non sequential write-once media the chain is vital 872 * to allow more and more descriptors to be written. The last descriptor 873 * written in an extent needs to claim space for a new extent. 874 */ 875 876 static int 877 udf_retrieve_lvint(struct udf_mount *ump, struct logvol_int_desc **lvintp) 878 { 879 union dscrptr *dscr; 880 struct logvol_int_desc *lvint; 881 uint32_t sector_size, sector, len; 882 int dscr_type, error; 883 884 sector_size = ump->discinfo.sector_size; 885 len = udf_rw32(ump->logical_vol->integrity_seq_loc.len); 886 sector = udf_rw32(ump->logical_vol->integrity_seq_loc.loc); 887 888 lvint = NULL; 889 dscr = NULL; 890 error = 0; 891 while (len) { 892 /* read in our integrity descriptor */ 893 error = udf_read_descriptor(ump, sector, M_UDFVOLD, &dscr); 894 if (!error) { 895 if (dscr == NULL) 896 break; /* empty terminates */ 897 dscr_type = udf_rw16(dscr->tag.id); 898 if (dscr_type == TAGID_TERM) { 899 break; /* clean terminator */ 900 } 901 if (dscr_type != TAGID_LOGVOL_INTEGRITY) { 902 /* fatal... corrupt disc */ 903 error = ENOENT; 904 break; 905 } 906 if (lvint) 907 free(lvint, M_UDFVOLD); 908 lvint = &dscr->lvid; 909 dscr = NULL; 910 } /* else hope for the best... maybe the next is ok */ 911 912 DPRINTFIF(VOLUMES, lvint, ("logvol integrity read, state %s\n", 913 udf_rw32(lvint->integrity_type) ? "CLOSED" : "OPEN")); 914 915 /* proceed sequential */ 916 sector += 1; 917 len -= sector_size; 918 919 /* are we linking to a new piece? */ 920 if (lvint->next_extent.len) { 921 len = udf_rw32(lvint->next_extent.len); 922 sector = udf_rw32(lvint->next_extent.loc); 923 } 924 } 925 926 /* clean up the mess, esp. when there is an error */ 927 if (dscr) 928 free(dscr, M_UDFVOLD); 929 930 if (error && lvint) { 931 free(lvint, M_UDFVOLD); 932 lvint = NULL; 933 } 934 935 if (!lvint) 936 error = ENOENT; 937 938 *lvintp = lvint; 939 return error; 940 } 941 942 /* --------------------------------------------------------------------- */ 943 944 /* 945 * Checks if ump's vds information is correct and complete 946 */ 947 948 int 949 udf_process_vds(struct udf_mount *ump, struct udf_args *args __unused) 950 { 951 union udf_pmap *mapping; 952 struct logvol_int_desc *lvint; 953 struct udf_logvol_info *lvinfo; 954 uint32_t n_pm, mt_l; 955 uint8_t *pmap_pos; 956 char *domain_name, *map_name; 957 const char *check_name; 958 int pmap_stype, pmap_size; 959 int pmap_type, log_part, phys_part; 960 int n_phys, n_virt, n_spar, n_meta; 961 int len, error; 962 963 if (ump == NULL) 964 return ENOENT; 965 966 /* we need at least an anchor (trivial, but for safety) */ 967 if (ump->anchors[0] == NULL) 968 return EINVAL; 969 970 /* we need at least one primary and one logical volume descriptor */ 971 if ((ump->primary_vol == NULL) || (ump->logical_vol) == NULL) 972 return EINVAL; 973 974 /* we need at least one partition descriptor */ 975 if (ump->partitions[0] == NULL) 976 return EINVAL; 977 978 /* check logical volume sector size verses device sector size */ 979 if (udf_rw32(ump->logical_vol->lb_size) != ump->discinfo.sector_size) { 980 printf("UDF mount: format violation, lb_size != sector size\n"); 981 return EINVAL; 982 } 983 984 domain_name = ump->logical_vol->domain_id.id; 985 if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) { 986 printf("mount_udf: disc not OSTA UDF Compliant, aborting\n"); 987 return EINVAL; 988 } 989 990 /* retrieve logical volume integrity sequence */ 991 error = udf_retrieve_lvint(ump, &ump->logvol_integrity); 992 993 /* 994 * We need at least one logvol integrity descriptor recorded. Note 995 * that its OK to have an open logical volume integrity here. The VAT 996 * will close/update the integrity. 997 */ 998 if (ump->logvol_integrity == NULL) 999 return EINVAL; 1000 1001 /* process derived structures */ 1002 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1003 lvint = ump->logvol_integrity; 1004 lvinfo = (struct udf_logvol_info *) (&lvint->tables[2 * n_pm]); 1005 ump->logvol_info = lvinfo; 1006 1007 /* TODO check udf versions? */ 1008 1009 /* 1010 * check logvol mappings: effective virt->log partmap translation 1011 * check and recording of the mapping results. Saves expensive 1012 * strncmp() in tight places. 1013 */ 1014 DPRINTF(VOLUMES, ("checking logvol mappings\n")); 1015 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1016 mt_l = udf_rw32(ump->logical_vol->mt_l); /* partmaps data length */ 1017 pmap_pos = ump->logical_vol->maps; 1018 1019 if (n_pm > UDF_PMAPS) { 1020 printf("UDF mount: too many mappings\n"); 1021 return EINVAL; 1022 } 1023 1024 n_phys = n_virt = n_spar = n_meta = 0; 1025 for (log_part = 0; log_part < n_pm; log_part++) { 1026 mapping = (union udf_pmap *) pmap_pos; 1027 pmap_stype = pmap_pos[0]; 1028 pmap_size = pmap_pos[1]; 1029 switch (pmap_stype) { 1030 case 1: /* physical mapping */ 1031 /* volseq = udf_rw16(mapping->pm1.vol_seq_num); */ 1032 phys_part = udf_rw16(mapping->pm1.part_num); 1033 pmap_type = UDF_VTOP_TYPE_PHYS; 1034 n_phys++; 1035 break; 1036 case 2: /* virtual/sparable/meta mapping */ 1037 map_name = mapping->pm2.part_id.id; 1038 /* volseq = udf_rw16(mapping->pm2.vol_seq_num); */ 1039 phys_part = udf_rw16(mapping->pm2.part_num); 1040 pmap_type = UDF_VTOP_TYPE_UNKNOWN; 1041 len = UDF_REGID_ID_SIZE; 1042 1043 check_name = "*UDF Virtual Partition"; 1044 if (strncmp(map_name, check_name, len) == 0) { 1045 pmap_type = UDF_VTOP_TYPE_VIRT; 1046 n_virt++; 1047 break; 1048 } 1049 check_name = "*UDF Sparable Partition"; 1050 if (strncmp(map_name, check_name, len) == 0) { 1051 pmap_type = UDF_VTOP_TYPE_SPARABLE; 1052 n_spar++; 1053 break; 1054 } 1055 check_name = "*UDF Metadata Partition"; 1056 if (strncmp(map_name, check_name, len) == 0) { 1057 pmap_type = UDF_VTOP_TYPE_META; 1058 n_meta++; 1059 break; 1060 } 1061 break; 1062 default: 1063 return EINVAL; 1064 } 1065 1066 DPRINTF(VOLUMES, ("\t%d -> %d type %d\n", log_part, phys_part, 1067 pmap_type)); 1068 if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) 1069 return EINVAL; 1070 1071 ump->vtop [log_part] = phys_part; 1072 ump->vtop_tp[log_part] = pmap_type; 1073 1074 pmap_pos += pmap_size; 1075 } 1076 /* not winning the beauty contest */ 1077 ump->vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW; 1078 1079 /* test some basic UDF assertions/requirements */ 1080 if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1)) 1081 return EINVAL; 1082 1083 if (n_virt) { 1084 if ((n_phys == 0) || n_spar || n_meta) 1085 return EINVAL; 1086 } 1087 if (n_spar + n_phys == 0) 1088 return EINVAL; 1089 1090 /* vat's can only be on a sequential media */ 1091 ump->data_alloc = UDF_ALLOC_SPACEMAP; 1092 if (n_virt) 1093 ump->data_alloc = UDF_ALLOC_SEQUENTIAL; 1094 1095 ump->meta_alloc = UDF_ALLOC_SPACEMAP; 1096 if (n_virt) 1097 ump->meta_alloc = UDF_ALLOC_VAT; 1098 if (n_meta) 1099 ump->meta_alloc = UDF_ALLOC_METABITMAP; 1100 1101 /* special cases for pseudo-overwrite */ 1102 if (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) { 1103 ump->data_alloc = UDF_ALLOC_SEQUENTIAL; 1104 if (n_meta) { 1105 ump->meta_alloc = UDF_ALLOC_METASEQUENTIAL; 1106 } else { 1107 ump->meta_alloc = UDF_ALLOC_RELAXEDSEQUENTIAL; 1108 } 1109 } 1110 1111 DPRINTF(VOLUMES, ("\tdata alloc scheme %d, meta alloc scheme %d\n", 1112 ump->data_alloc, ump->meta_alloc)); 1113 /* TODO determine partitions to write data and metadata ? */ 1114 1115 /* signal its OK for now */ 1116 return 0; 1117 } 1118 1119 /* --------------------------------------------------------------------- */ 1120 1121 /* 1122 * Read in complete VAT file and check if its indeed a VAT file descriptor 1123 */ 1124 1125 static int 1126 udf_check_for_vat(struct udf_node *vat_node) 1127 { 1128 struct udf_mount *ump; 1129 struct icb_tag *icbtag; 1130 struct timestamp *mtime; 1131 struct regid *regid; 1132 struct udf_vat *vat; 1133 struct udf_logvol_info *lvinfo; 1134 uint32_t vat_length, alloc_length; 1135 uint32_t vat_offset, vat_entries; 1136 uint32_t sector_size; 1137 uint32_t sectors; 1138 uint32_t *raw_vat; 1139 char *regid_name; 1140 int filetype; 1141 int error; 1142 1143 /* vat_length is really 64 bits though impossible */ 1144 1145 DPRINTF(VOLUMES, ("Checking for VAT\n")); 1146 if (!vat_node) 1147 return ENOENT; 1148 1149 /* get mount info */ 1150 ump = vat_node->ump; 1151 1152 /* check assertions */ 1153 assert(vat_node->fe || vat_node->efe); 1154 assert(ump->logvol_integrity); 1155 1156 /* get information from fe/efe */ 1157 if (vat_node->fe) { 1158 vat_length = udf_rw64(vat_node->fe->inf_len); 1159 icbtag = &vat_node->fe->icbtag; 1160 mtime = &vat_node->fe->mtime; 1161 } else { 1162 vat_length = udf_rw64(vat_node->efe->inf_len); 1163 icbtag = &vat_node->efe->icbtag; 1164 mtime = &vat_node->efe->mtime; 1165 } 1166 1167 /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */ 1168 filetype = icbtag->file_type; 1169 if ((filetype != 0) && (filetype != UDF_ICB_FILETYPE_VAT)) 1170 return ENOENT; 1171 1172 DPRINTF(VOLUMES, ("\tPossible VAT length %d\n", vat_length)); 1173 /* place a sanity check on the length; currently 1Mb in size */ 1174 if (vat_length > 1*1024*1024) 1175 return ENOENT; 1176 1177 /* get sector size */ 1178 sector_size = vat_node->ump->discinfo.sector_size; 1179 1180 /* calculate how many sectors to read in and how much to allocate */ 1181 sectors = (vat_length + sector_size -1) / sector_size; 1182 alloc_length = (sectors + 2) * sector_size; 1183 1184 /* try to allocate the space */ 1185 ump->vat_table_alloc_length = alloc_length; 1186 ump->vat_table = malloc(alloc_length, M_UDFVOLD, M_CANFAIL | M_WAITOK); 1187 if (!ump->vat_table) 1188 return ENOMEM; /* impossible to allocate */ 1189 DPRINTF(VOLUMES, ("\talloced fine\n")); 1190 1191 /* read it in! */ 1192 raw_vat = (uint32_t *) ump->vat_table; 1193 error = udf_read_file_extent(vat_node, 0, sectors, (uint8_t *) raw_vat); 1194 if (error) { 1195 DPRINTF(VOLUMES, ("\tread failed : %d\n", error)); 1196 /* not completely readable... :( bomb out */ 1197 free(ump->vat_table, M_UDFVOLD); 1198 ump->vat_table = NULL; 1199 return error; 1200 } 1201 DPRINTF(VOLUMES, ("VAT read in fine!\n")); 1202 1203 /* 1204 * check contents of the file if its the old 1.50 VAT table format. 1205 * Its notoriously broken and allthough some implementations support an 1206 * extention as defined in the UDF 1.50 errata document, its doubtfull 1207 * to be useable since a lot of implementations don't maintain it. 1208 */ 1209 lvinfo = ump->logvol_info; 1210 1211 if (filetype == 0) { 1212 /* definition */ 1213 vat_offset = 0; 1214 vat_entries = (vat_length-36)/4; 1215 1216 /* check 1.50 VAT */ 1217 regid = (struct regid *) (raw_vat + vat_entries); 1218 regid_name = (char *) regid->id; 1219 error = strncmp(regid_name, "*UDF Virtual Alloc Tbl", 22); 1220 if (error) { 1221 DPRINTF(VOLUMES, ("VAT format 1.50 rejected\n")); 1222 free(ump->vat_table, M_UDFVOLD); 1223 ump->vat_table = NULL; 1224 return ENOENT; 1225 } 1226 /* TODO update LVID from "*UDF VAT LVExtension" ext. attr. */ 1227 } else { 1228 vat = (struct udf_vat *) raw_vat; 1229 1230 /* definition */ 1231 vat_offset = vat->header_len; 1232 vat_entries = (vat_length - vat_offset)/4; 1233 1234 assert(lvinfo); 1235 lvinfo->num_files = vat->num_files; 1236 lvinfo->num_directories = vat->num_directories; 1237 lvinfo->min_udf_readver = vat->min_udf_readver; 1238 lvinfo->min_udf_writever = vat->min_udf_writever; 1239 lvinfo->max_udf_writever = vat->max_udf_writever; 1240 } 1241 1242 ump->vat_offset = vat_offset; 1243 ump->vat_entries = vat_entries; 1244 1245 DPRINTF(VOLUMES, ("VAT format accepted, marking it closed\n")); 1246 ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED); 1247 ump->logvol_integrity->time = *mtime; 1248 1249 return 0; /* success! */ 1250 } 1251 1252 /* --------------------------------------------------------------------- */ 1253 1254 static int 1255 udf_search_vat(struct udf_mount *ump, union udf_pmap *mapping) 1256 { 1257 struct udf_node *vat_node; 1258 struct long_ad icb_loc; 1259 uint32_t early_vat_loc, late_vat_loc, vat_loc; 1260 int error; 1261 1262 /* mapping info not needed */ 1263 mapping = mapping; 1264 1265 vat_loc = ump->last_possible_vat_location; 1266 early_vat_loc = vat_loc - 2 * ump->discinfo.blockingnr; 1267 early_vat_loc = MAX(early_vat_loc, ump->first_possible_vat_location); 1268 late_vat_loc = vat_loc + 1024; 1269 1270 /* TODO first search last sector? */ 1271 do { 1272 DPRINTF(VOLUMES, ("Checking for VAT at sector %d\n", vat_loc)); 1273 icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART); 1274 icb_loc.loc.lb_num = udf_rw32(vat_loc); 1275 1276 error = udf_get_node(ump, &icb_loc, &vat_node); 1277 if (!error) error = udf_check_for_vat(vat_node); 1278 if (!error) break; 1279 if (vat_node) { 1280 vput(vat_node->vnode); 1281 udf_dispose_node(vat_node); 1282 } 1283 vat_loc--; /* walk backwards */ 1284 } while (vat_loc >= early_vat_loc); 1285 1286 /* we don't need our VAT node anymore */ 1287 if (vat_node) { 1288 vput(vat_node->vnode); 1289 udf_dispose_node(vat_node); 1290 } 1291 1292 return error; 1293 } 1294 1295 /* --------------------------------------------------------------------- */ 1296 1297 static int 1298 udf_read_sparables(struct udf_mount *ump, union udf_pmap *mapping) 1299 { 1300 union dscrptr *dscr; 1301 struct part_map_spare *pms = (struct part_map_spare *) mapping; 1302 uint32_t lb_num; 1303 int spar, error; 1304 1305 /* 1306 * The partition mapping passed on to us specifies the information we 1307 * need to locate and initialise the sparable partition mapping 1308 * information we need. 1309 */ 1310 1311 DPRINTF(VOLUMES, ("Read sparable table\n")); 1312 ump->sparable_packet_len = udf_rw16(pms->packet_len); 1313 for (spar = 0; spar < pms->n_st; spar++) { 1314 lb_num = pms->st_loc[spar]; 1315 DPRINTF(VOLUMES, ("Checking for sparing table %d\n", lb_num)); 1316 error = udf_read_descriptor(ump, lb_num, M_UDFVOLD, &dscr); 1317 if (!error && dscr) { 1318 if (udf_rw16(dscr->tag.id) == TAGID_SPARING_TABLE) { 1319 if (ump->sparing_table) 1320 free(ump->sparing_table, M_UDFVOLD); 1321 ump->sparing_table = &dscr->spt; 1322 dscr = NULL; 1323 DPRINTF(VOLUMES, 1324 ("Sparing table accepted (%d entries)\n", 1325 udf_rw16(ump->sparing_table->rt_l))); 1326 break; /* we're done */ 1327 } 1328 } 1329 if (dscr) 1330 free(dscr, M_UDFVOLD); 1331 } 1332 1333 if (ump->sparing_table) 1334 return 0; 1335 1336 return ENOENT; 1337 } 1338 1339 /* --------------------------------------------------------------------- */ 1340 1341 int 1342 udf_read_vds_tables(struct udf_mount *ump, struct udf_args *args __unused) 1343 { 1344 union udf_pmap *mapping; 1345 uint32_t n_pm, mt_l; 1346 uint32_t log_part; 1347 uint8_t *pmap_pos; 1348 int pmap_size; 1349 int error; 1350 1351 /* We have to iterate again over the part mappings for locations */ 1352 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1353 mt_l = udf_rw32(ump->logical_vol->mt_l); /* partmaps data length */ 1354 pmap_pos = ump->logical_vol->maps; 1355 1356 for (log_part = 0; log_part < n_pm; log_part++) { 1357 mapping = (union udf_pmap *) pmap_pos; 1358 switch (ump->vtop_tp[log_part]) { 1359 case UDF_VTOP_TYPE_PHYS : 1360 /* nothing */ 1361 break; 1362 case UDF_VTOP_TYPE_VIRT : 1363 /* search and load VAT */ 1364 error = udf_search_vat(ump, mapping); 1365 if (error) 1366 return ENOENT; 1367 break; 1368 case UDF_VTOP_TYPE_SPARABLE : 1369 /* load one of the sparable tables */ 1370 error = udf_read_sparables(ump, mapping); 1371 if (error) 1372 return ENOENT; 1373 break; 1374 case UDF_VTOP_TYPE_META : 1375 /* TODO load metafile and metabitmapfile FE/EFEs */ 1376 return ENOENT; 1377 default: 1378 break; 1379 } 1380 pmap_size = pmap_pos[1]; 1381 pmap_pos += pmap_size; 1382 } 1383 1384 return 0; 1385 } 1386 1387 /* --------------------------------------------------------------------- */ 1388 1389 int 1390 udf_read_rootdirs(struct udf_mount *ump, struct udf_args *args __unused) 1391 { 1392 struct udf_node *rootdir_node, *streamdir_node; 1393 union dscrptr *dscr; 1394 struct long_ad fsd_loc, *dir_loc; 1395 uint32_t lb_num, dummy; 1396 uint32_t fsd_len; 1397 int dscr_type; 1398 int error; 1399 1400 /* TODO implement FSD reading in seperate function like integrity? */ 1401 /* get fileset descriptor sequence */ 1402 fsd_loc = ump->logical_vol->lv_fsd_loc; 1403 fsd_len = udf_rw32(fsd_loc.len); 1404 1405 dscr = NULL; 1406 error = 0; 1407 while (fsd_len || error) { 1408 DPRINTF(VOLUMES, ("fsd_len = %d\n", fsd_len)); 1409 /* translate fsd_loc to lb_num */ 1410 error = udf_translate_vtop(ump, &fsd_loc, &lb_num, &dummy); 1411 if (error) 1412 break; 1413 DPRINTF(VOLUMES, ("Reading FSD at lb %d\n", lb_num)); 1414 error = udf_read_descriptor(ump, lb_num, M_UDFVOLD, &dscr); 1415 /* end markers */ 1416 if (error || (dscr == NULL)) 1417 break; 1418 1419 /* analyse */ 1420 dscr_type = udf_rw16(dscr->tag.id); 1421 if (dscr_type == TAGID_TERM) 1422 break; 1423 if (dscr_type != TAGID_FSD) { 1424 free(dscr, M_UDFVOLD); 1425 return ENOENT; 1426 } 1427 1428 /* 1429 * TODO check for multiple fileset descriptors; its only 1430 * picking the last now. Also check for FSD 1431 * correctness/interpretability 1432 */ 1433 1434 /* update */ 1435 if (ump->fileset_desc) { 1436 free(ump->fileset_desc, M_UDFVOLD); 1437 } 1438 ump->fileset_desc = &dscr->fsd; 1439 dscr = NULL; 1440 1441 /* continue to the next fsd */ 1442 fsd_len -= ump->discinfo.sector_size; 1443 fsd_loc.loc.lb_num = udf_rw32(udf_rw32(fsd_loc.loc.lb_num)+1); 1444 1445 /* follow up to fsd->next_ex (long_ad) if its not null */ 1446 if (udf_rw32(ump->fileset_desc->next_ex.len)) { 1447 DPRINTF(VOLUMES, ("follow up FSD extent\n")); 1448 fsd_loc = ump->fileset_desc->next_ex; 1449 fsd_len = udf_rw32(ump->fileset_desc->next_ex.len); 1450 } 1451 } 1452 if (dscr) 1453 free(dscr, M_UDFVOLD); 1454 1455 /* there has to be one */ 1456 if (ump->fileset_desc == NULL) 1457 return ENOENT; 1458 1459 DPRINTF(VOLUMES, ("FSD read in fine\n")); 1460 1461 /* 1462 * Now the FSD is known, read in the rootdirectory and if one exists, 1463 * the system stream dir. Some files in the system streamdir are not 1464 * wanted in this implementation since they are not maintained. If 1465 * writing is enabled we'll delete these files if they exist. 1466 */ 1467 1468 rootdir_node = streamdir_node = NULL; 1469 dir_loc = NULL; 1470 1471 /* try to read in the rootdir */ 1472 dir_loc = &ump->fileset_desc->rootdir_icb; 1473 error = udf_get_node(ump, dir_loc, &rootdir_node); 1474 if (error) 1475 return ENOENT; 1476 1477 /* aparently it read in fine */ 1478 1479 /* 1480 * Try the system stream directory; not very likely in the ones we 1481 * test, but for completeness. 1482 */ 1483 dir_loc = &ump->fileset_desc->streamdir_icb; 1484 if (udf_rw32(dir_loc->len)) { 1485 error = udf_get_node(ump, dir_loc, &streamdir_node); 1486 if (error) 1487 printf("udf mount: streamdir defined but ignored\n"); 1488 if (!error) { 1489 /* 1490 * TODO process streamdir `baddies' i.e. files we dont 1491 * want if R/W 1492 */ 1493 } 1494 } 1495 1496 DPRINTF(VOLUMES, ("Rootdir(s) read in fine\n")); 1497 1498 /* release the vnodes again; they'll be auto-recycled later */ 1499 if (streamdir_node) { 1500 vput(streamdir_node->vnode); 1501 } 1502 if (rootdir_node) { 1503 vput(rootdir_node->vnode); 1504 } 1505 1506 return 0; 1507 } 1508 1509 /* --------------------------------------------------------------------- */ 1510 1511 int 1512 udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc, 1513 uint32_t *lb_numres, uint32_t *extres) 1514 { 1515 struct part_desc *pdesc; 1516 struct spare_map_entry *sme; 1517 uint32_t *trans; 1518 uint32_t lb_num, lb_rel, lb_packet; 1519 int rel, vpart, part; 1520 1521 assert(ump && icb_loc && lb_numres); 1522 1523 vpart = udf_rw16(icb_loc->loc.part_num); 1524 lb_num = udf_rw32(icb_loc->loc.lb_num); 1525 if (vpart < 0 || vpart > UDF_VTOP_RAWPART) 1526 return EINVAL; 1527 1528 switch (ump->vtop_tp[vpart]) { 1529 case UDF_VTOP_TYPE_RAW : 1530 /* 1:1 to the end of the device */ 1531 *lb_numres = lb_num; 1532 *extres = INT_MAX; 1533 return 0; 1534 case UDF_VTOP_TYPE_PHYS : 1535 /* transform into its disc logical block */ 1536 part = ump->vtop[vpart]; 1537 pdesc = ump->partitions[part]; 1538 if (lb_num > udf_rw32(pdesc->part_len)) 1539 return EINVAL; 1540 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1541 1542 /* extent from here to the end of the partition */ 1543 *extres = udf_rw32(pdesc->part_len) - lb_num; 1544 return 0; 1545 case UDF_VTOP_TYPE_VIRT : 1546 /* only maps one sector, lookup in VAT */ 1547 if (lb_num >= ump->vat_entries) /* XXX > or >= ? */ 1548 return EINVAL; 1549 1550 /* lookup in virtual allocation table */ 1551 trans = (uint32_t *) (ump->vat_table + ump->vat_offset); 1552 lb_num = udf_rw32(trans[lb_num]); 1553 1554 /* transform into its disc logical block */ 1555 part = ump->vtop[vpart]; 1556 pdesc = ump->partitions[part]; 1557 if (lb_num > udf_rw32(pdesc->part_len)) 1558 return EINVAL; 1559 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1560 1561 /* just one logical block */ 1562 *extres = 1; 1563 return 0; 1564 case UDF_VTOP_TYPE_SPARABLE : 1565 /* check if the packet containing the lb_num is remapped */ 1566 lb_packet = lb_num / ump->sparable_packet_len; 1567 lb_rel = lb_num % ump->sparable_packet_len; 1568 1569 for (rel = 0; rel < udf_rw16(ump->sparing_table->rt_l); rel++) { 1570 sme = &ump->sparing_table->entries[rel]; 1571 if (lb_packet == udf_rw32(sme->org)) { 1572 /* NOTE maps to absolute disc logical block! */ 1573 *lb_numres = udf_rw32(sme->map) + lb_rel; 1574 *extres = ump->sparable_packet_len - lb_rel; 1575 return 0; 1576 } 1577 } 1578 1579 /* transform into its disc logical block */ 1580 part = ump->vtop[vpart]; 1581 pdesc = ump->partitions[part]; 1582 if (lb_num > udf_rw32(pdesc->part_len)) 1583 return EINVAL; 1584 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1585 1586 /* rest of block */ 1587 *extres = ump->sparable_packet_len - lb_rel; 1588 return 0; 1589 case UDF_VTOP_TYPE_META : 1590 default: 1591 printf("UDF vtop translation scheme %d unimplemented yet\n", 1592 ump->vtop_tp[vpart]); 1593 } 1594 1595 return EINVAL; 1596 } 1597 1598 /* --------------------------------------------------------------------- */ 1599 1600 /* To make absolutely sure we are NOT returning zero, add one :) */ 1601 1602 long 1603 udf_calchash(struct long_ad *icbptr) 1604 { 1605 /* ought to be enough since each mountpoint has its own chain */ 1606 return udf_rw32(icbptr->loc.lb_num) + 1; 1607 } 1608 1609 /* --------------------------------------------------------------------- */ 1610 1611 static struct udf_node * 1612 udf_hashget(struct udf_mount *ump, struct long_ad *icbptr) 1613 { 1614 struct udf_node *unp; 1615 struct vnode *vp; 1616 uint32_t hashline; 1617 1618 loop: 1619 simple_lock(&ump->ihash_slock); 1620 1621 hashline = udf_calchash(icbptr) & UDF_INODE_HASHMASK; 1622 LIST_FOREACH(unp, &ump->udf_nodes[hashline], hashchain) { 1623 assert(unp); 1624 if (unp->loc.loc.lb_num == icbptr->loc.lb_num && 1625 unp->loc.loc.part_num == icbptr->loc.part_num) { 1626 vp = unp->vnode; 1627 assert(vp); 1628 simple_lock(&vp->v_interlock); 1629 simple_unlock(&ump->ihash_slock); 1630 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) 1631 goto loop; 1632 return unp; 1633 } 1634 } 1635 simple_unlock(&ump->ihash_slock); 1636 1637 return NULL; 1638 } 1639 1640 /* --------------------------------------------------------------------- */ 1641 1642 static void 1643 udf_hashins(struct udf_node *unp) 1644 { 1645 struct udf_mount *ump; 1646 uint32_t hashline; 1647 1648 ump = unp->ump; 1649 simple_lock(&ump->ihash_slock); 1650 1651 hashline = udf_calchash(&unp->loc) & UDF_INODE_HASHMASK; 1652 LIST_INSERT_HEAD(&ump->udf_nodes[hashline], unp, hashchain); 1653 1654 simple_unlock(&ump->ihash_slock); 1655 } 1656 1657 /* --------------------------------------------------------------------- */ 1658 1659 static void 1660 udf_hashrem(struct udf_node *unp) 1661 { 1662 struct udf_mount *ump; 1663 1664 ump = unp->ump; 1665 simple_lock(&ump->ihash_slock); 1666 1667 LIST_REMOVE(unp, hashchain); 1668 1669 simple_unlock(&ump->ihash_slock); 1670 } 1671 1672 /* --------------------------------------------------------------------- */ 1673 1674 int 1675 udf_dispose_locked_node(struct udf_node *node) 1676 { 1677 if (!node) 1678 return 0; 1679 if (node->vnode) 1680 VOP_UNLOCK(node->vnode, 0); 1681 return udf_dispose_node(node); 1682 } 1683 1684 /* --------------------------------------------------------------------- */ 1685 1686 int 1687 udf_dispose_node(struct udf_node *node) 1688 { 1689 struct vnode *vp; 1690 1691 DPRINTF(NODE, ("udf_dispose_node called on node %p\n", node)); 1692 if (!node) { 1693 DPRINTF(NODE, ("UDF: Dispose node on node NULL, ignoring\n")); 1694 return 0; 1695 } 1696 1697 vp = node->vnode; 1698 1699 /* TODO extended attributes and streamdir */ 1700 1701 /* remove from our hash lookup table */ 1702 udf_hashrem(node); 1703 1704 /* dissociate our udf_node from the vnode */ 1705 vp->v_data = NULL; 1706 1707 /* free associated memory and the node itself */ 1708 if (node->fe) 1709 pool_put(node->ump->desc_pool, node->fe); 1710 if (node->efe) 1711 pool_put(node->ump->desc_pool, node->efe); 1712 pool_put(&udf_node_pool, node); 1713 1714 return 0; 1715 } 1716 1717 /* --------------------------------------------------------------------- */ 1718 1719 /* 1720 * Genfs interfacing 1721 * 1722 * static const struct genfs_ops udffs_genfsops = { 1723 * .gop_size = genfs_size, 1724 * size of transfers 1725 * .gop_alloc = udf_gop_alloc, 1726 * unknown 1727 * .gop_write = genfs_gop_write, 1728 * putpages interface code 1729 * .gop_markupdate = udf_gop_markupdate, 1730 * set update/modify flags etc. 1731 * } 1732 */ 1733 1734 /* 1735 * Genfs interface. These four functions are the only ones defined though not 1736 * documented... great.... why is chosen for the `.' initialisers i dont know 1737 * but other filingsystems seem to use it this way. 1738 */ 1739 1740 static int 1741 udf_gop_alloc(struct vnode *vp __unused, off_t off __unused, 1742 off_t len __unused, int flags __unused, kauth_cred_t cred __unused) 1743 { 1744 return 0; 1745 } 1746 1747 1748 static void 1749 udf_gop_markupdate(struct vnode *vp, int flags __unused) 1750 { 1751 struct udf_node *udf_node = VTOI(vp); 1752 u_long mask; 1753 1754 udf_node = udf_node; /* shut up gcc */ 1755 1756 mask = 0; 1757 #ifdef notyet 1758 if ((flags & GOP_UPDATE_ACCESSED) != 0) { 1759 mask = UDF_SET_ACCESS; 1760 } 1761 if ((flags & GOP_UPDATE_MODIFIED) != 0) { 1762 mask |= UDF_SET_UPDATE; 1763 } 1764 if (mask) { 1765 udf_node->update_flag |= mask; 1766 } 1767 #endif 1768 /* msdosfs doesn't do it, but shouldn't we update the times here? */ 1769 } 1770 1771 1772 static const struct genfs_ops udf_genfsops = { 1773 .gop_size = genfs_size, 1774 .gop_alloc = udf_gop_alloc, 1775 .gop_write = genfs_gop_write, 1776 .gop_markupdate = udf_gop_markupdate, 1777 }; 1778 1779 /* --------------------------------------------------------------------- */ 1780 1781 /* 1782 * Each node can have an attached streamdir node though not 1783 * recursively. These are otherwise known as named substreams/named 1784 * extended attributes that have no size limitations. 1785 * 1786 * `Normal' extended attributes are indicated with a number and are recorded 1787 * in either the fe/efe descriptor itself for small descriptors or recorded in 1788 * the attached extended attribute file. Since this file can get fragmented, 1789 * care ought to be taken. 1790 */ 1791 1792 int 1793 udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, 1794 struct udf_node **noderes) 1795 { 1796 union dscrptr *dscr, *tmpdscr; 1797 struct udf_node *node; 1798 struct vnode *nvp; 1799 struct long_ad icb_loc; 1800 extern int (**udf_vnodeop_p)(void *); 1801 uint64_t file_size; 1802 uint32_t lb_size, sector, dummy; 1803 int udf_file_type, dscr_type, strat, strat4096, needs_indirect; 1804 int error; 1805 1806 DPRINTF(NODE, ("udf_get_node called\n")); 1807 *noderes = node = NULL; 1808 1809 /* lock to disallow simultanious creation of same node */ 1810 lockmgr(&ump->get_node_lock, LK_EXCLUSIVE, NULL); 1811 1812 DPRINTF(NODE, ("\tlookup in hash table\n")); 1813 /* lookup in hash table */ 1814 assert(ump); 1815 assert(node_icb_loc); 1816 node = udf_hashget(ump, node_icb_loc); 1817 if (node) { 1818 DPRINTF(NODE, ("\tgot it from the hash!\n")); 1819 /* vnode is returned locked */ 1820 *noderes = node; 1821 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1822 return 0; 1823 } 1824 1825 /* garbage check: translate node_icb_loc to sectornr */ 1826 error = udf_translate_vtop(ump, node_icb_loc, §or, &dummy); 1827 if (error) { 1828 /* no use, this will fail anyway */ 1829 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1830 return EINVAL; 1831 } 1832 1833 /* build node (do initialise!) */ 1834 node = pool_get(&udf_node_pool, PR_WAITOK); 1835 memset(node, 0, sizeof(struct udf_node)); 1836 1837 DPRINTF(NODE, ("\tget new vnode\n")); 1838 /* give it a vnode */ 1839 error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, &nvp); 1840 if (error) { 1841 pool_put(&udf_node_pool, node); 1842 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1843 return error; 1844 } 1845 1846 /* allways return locked vnode */ 1847 if ((error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY))) { 1848 /* recycle vnode and unlock; simultanious will fail too */ 1849 ungetnewvnode(nvp); 1850 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1851 return error; 1852 } 1853 1854 /* initialise crosslinks, note location of fe/efe for hashing */ 1855 node->ump = ump; 1856 node->vnode = nvp; 1857 nvp->v_data = node; 1858 node->loc = *node_icb_loc; 1859 node->lockf = 0; 1860 1861 /* insert into the hash lookup */ 1862 udf_hashins(node); 1863 1864 /* safe to unlock, the entry is in the hash table, vnode is locked */ 1865 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1866 1867 icb_loc = *node_icb_loc; 1868 needs_indirect = 0; 1869 strat4096 = 0; 1870 udf_file_type = UDF_ICB_FILETYPE_UNKNOWN; 1871 file_size = 0; 1872 lb_size = udf_rw32(ump->logical_vol->lb_size); 1873 1874 do { 1875 error = udf_translate_vtop(ump, &icb_loc, §or, &dummy); 1876 if (error) 1877 break; 1878 1879 /* try to read in fe/efe */ 1880 error = udf_read_descriptor(ump, sector, M_UDFTEMP, &tmpdscr); 1881 1882 /* blank sector marks end of sequence, check this */ 1883 if ((tmpdscr == NULL) && (!strat4096)) 1884 error = ENOENT; 1885 1886 /* break if read error or blank sector */ 1887 if (error || (tmpdscr == NULL)) 1888 break; 1889 1890 /* process descriptor based on the descriptor type */ 1891 dscr_type = udf_rw16(tmpdscr->tag.id); 1892 1893 /* if dealing with an indirect entry, follow the link */ 1894 if (dscr_type == TAGID_INDIRECT_ENTRY) { 1895 needs_indirect = 0; 1896 icb_loc = tmpdscr->inde.indirect_icb; 1897 free(tmpdscr, M_UDFTEMP); 1898 continue; 1899 } 1900 1901 /* only file entries and extended file entries allowed here */ 1902 if ((dscr_type != TAGID_FENTRY) && 1903 (dscr_type != TAGID_EXTFENTRY)) { 1904 free(tmpdscr, M_UDFTEMP); 1905 error = ENOENT; 1906 break; 1907 } 1908 1909 /* get descriptor space from our pool */ 1910 KASSERT(udf_tagsize(tmpdscr, lb_size) == lb_size); 1911 1912 dscr = pool_get(ump->desc_pool, PR_WAITOK); 1913 memcpy(dscr, tmpdscr, lb_size); 1914 free(tmpdscr, M_UDFTEMP); 1915 1916 /* record and process/update (ext)fentry */ 1917 if (dscr_type == TAGID_FENTRY) { 1918 if (node->fe) 1919 pool_put(ump->desc_pool, node->fe); 1920 node->fe = &dscr->fe; 1921 strat = udf_rw16(node->fe->icbtag.strat_type); 1922 udf_file_type = node->fe->icbtag.file_type; 1923 file_size = udf_rw64(node->fe->inf_len); 1924 } else { 1925 if (node->efe) 1926 pool_put(ump->desc_pool, node->efe); 1927 node->efe = &dscr->efe; 1928 strat = udf_rw16(node->efe->icbtag.strat_type); 1929 udf_file_type = node->efe->icbtag.file_type; 1930 file_size = udf_rw64(node->efe->inf_len); 1931 } 1932 1933 /* check recording strategy (structure) */ 1934 1935 /* 1936 * Strategy 4096 is a daisy linked chain terminating with an 1937 * unrecorded sector or a TERM descriptor. The next 1938 * descriptor is to be found in the sector that follows the 1939 * current sector. 1940 */ 1941 if (strat == 4096) { 1942 strat4096 = 1; 1943 needs_indirect = 1; 1944 1945 icb_loc.loc.lb_num = udf_rw32(icb_loc.loc.lb_num) + 1; 1946 } 1947 1948 /* 1949 * Strategy 4 is the normal strategy and terminates, but if 1950 * we're in strategy 4096, we can't have strategy 4 mixed in 1951 */ 1952 1953 if (strat == 4) { 1954 if (strat4096) { 1955 error = EINVAL; 1956 break; 1957 } 1958 break; /* done */ 1959 } 1960 } while (!error); 1961 1962 if (error) { 1963 /* recycle udf_node */ 1964 udf_dispose_node(node); 1965 1966 /* recycle vnode */ 1967 nvp->v_data = NULL; 1968 ungetnewvnode(nvp); 1969 1970 return EINVAL; /* error code ok? */ 1971 } 1972 1973 /* post process and initialise node */ 1974 1975 /* assert no references to dscr anymore beyong this point */ 1976 assert((node->fe) || (node->efe)); 1977 dscr = NULL; 1978 1979 /* 1980 * Record where to record an updated version of the descriptor. If 1981 * there is a sequence of indirect entries, icb_loc will have been 1982 * updated. Its the write disipline to allocate new space and to make 1983 * sure the chain is maintained. 1984 * 1985 * `needs_indirect' flags if the next location is to be filled with 1986 * with an indirect entry. 1987 */ 1988 node->next_loc = icb_loc; 1989 node->needs_indirect = needs_indirect; 1990 1991 /* 1992 * Translate UDF filetypes into vnode types. 1993 * 1994 * Systemfiles like the meta main and mirror files are not treated as 1995 * normal files, so we type them as having no type. UDF dictates that 1996 * they are not allowed to be visible. 1997 */ 1998 1999 /* TODO specfs, fifofs etc etc. vnops setting */ 2000 switch (udf_file_type) { 2001 case UDF_ICB_FILETYPE_DIRECTORY : 2002 case UDF_ICB_FILETYPE_STREAMDIR : 2003 nvp->v_type = VDIR; 2004 break; 2005 case UDF_ICB_FILETYPE_BLOCKDEVICE : 2006 nvp->v_type = VBLK; 2007 break; 2008 case UDF_ICB_FILETYPE_CHARDEVICE : 2009 nvp->v_type = VCHR; 2010 break; 2011 case UDF_ICB_FILETYPE_SYMLINK : 2012 nvp->v_type = VLNK; 2013 break; 2014 case UDF_ICB_FILETYPE_META_MAIN : 2015 case UDF_ICB_FILETYPE_META_MIRROR : 2016 nvp->v_type = VNON; 2017 break; 2018 case UDF_ICB_FILETYPE_RANDOMACCESS : 2019 nvp->v_type = VREG; 2020 break; 2021 default: 2022 /* YIKES, either a block/char device, fifo or something else */ 2023 nvp->v_type = VNON; 2024 } 2025 2026 /* initialise genfs */ 2027 genfs_node_init(nvp, &udf_genfsops); 2028 2029 /* don't forget to set vnode's v_size */ 2030 nvp->v_size = file_size; 2031 2032 /* TODO ext attr and streamdir nodes */ 2033 2034 *noderes = node; 2035 2036 return 0; 2037 } 2038 2039 /* --------------------------------------------------------------------- */ 2040 2041 /* UDF<->unix converters */ 2042 2043 /* --------------------------------------------------------------------- */ 2044 2045 static mode_t 2046 udf_perm_to_unix_mode(uint32_t perm) 2047 { 2048 mode_t mode; 2049 2050 mode = ((perm & UDF_FENTRY_PERM_USER_MASK) ); 2051 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK ) >> 2); 2052 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 2053 2054 return mode; 2055 } 2056 2057 /* --------------------------------------------------------------------- */ 2058 2059 #ifdef notyet 2060 static uint32_t 2061 unix_mode_to_udf_perm(mode_t mode) 2062 { 2063 uint32_t perm; 2064 2065 perm = ((mode & S_IRWXO) ); 2066 perm |= ((mode & S_IRWXG) << 2); 2067 perm |= ((mode & S_IRWXU) << 4); 2068 perm |= ((mode & S_IWOTH) << 3); 2069 perm |= ((mode & S_IWGRP) << 5); 2070 perm |= ((mode & S_IWUSR) << 7); 2071 2072 return perm; 2073 } 2074 #endif 2075 2076 /* --------------------------------------------------------------------- */ 2077 2078 static uint32_t 2079 udf_icb_to_unix_filetype(uint32_t icbftype) 2080 { 2081 switch (icbftype) { 2082 case UDF_ICB_FILETYPE_DIRECTORY : 2083 case UDF_ICB_FILETYPE_STREAMDIR : 2084 return S_IFDIR; 2085 case UDF_ICB_FILETYPE_FIFO : 2086 return S_IFIFO; 2087 case UDF_ICB_FILETYPE_CHARDEVICE : 2088 return S_IFCHR; 2089 case UDF_ICB_FILETYPE_BLOCKDEVICE : 2090 return S_IFBLK; 2091 case UDF_ICB_FILETYPE_RANDOMACCESS : 2092 return S_IFREG; 2093 case UDF_ICB_FILETYPE_SYMLINK : 2094 return S_IFLNK; 2095 case UDF_ICB_FILETYPE_SOCKET : 2096 return S_IFSOCK; 2097 } 2098 /* no idea what this is */ 2099 return 0; 2100 } 2101 2102 /* --------------------------------------------------------------------- */ 2103 2104 /* TODO KNF-ify */ 2105 2106 void 2107 udf_to_unix_name(char *result, char *id, int len, struct charspec *chsp) 2108 { 2109 uint16_t *raw_name, *unix_name; 2110 uint16_t *inchp, ch; 2111 uint8_t *outchp; 2112 int ucode_chars, nice_uchars; 2113 2114 raw_name = malloc(2048 * sizeof(uint16_t), M_UDFTEMP, M_WAITOK); 2115 unix_name = raw_name + 1024; /* split space in half */ 2116 assert(sizeof(char) == sizeof(uint8_t)); 2117 outchp = (uint8_t *) result; 2118 if ((chsp->type == 0) && (strcmp((char*) chsp->inf, "OSTA Compressed Unicode") == 0)) { 2119 *raw_name = *unix_name = 0; 2120 ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name); 2121 ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name)); 2122 nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars); 2123 for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) { 2124 ch = *inchp; 2125 /* XXX sloppy unicode -> latin */ 2126 *outchp++ = ch & 255; 2127 if (!ch) break; 2128 } 2129 *outchp++ = 0; 2130 } else { 2131 /* assume 8bit char length byte latin-1 */ 2132 assert(*id == 8); 2133 strncpy((char *) result, (char *) (id+1), strlen((char *) (id+1))); 2134 } 2135 free(raw_name, M_UDFTEMP); 2136 } 2137 2138 /* --------------------------------------------------------------------- */ 2139 2140 /* TODO KNF-ify */ 2141 2142 void 2143 unix_to_udf_name(char *result, char *name, 2144 uint8_t *result_len, struct charspec *chsp) 2145 { 2146 uint16_t *raw_name; 2147 int udf_chars, name_len; 2148 char *inchp; 2149 uint16_t *outchp; 2150 2151 raw_name = malloc(1024, M_UDFTEMP, M_WAITOK); 2152 /* convert latin-1 or whatever to unicode-16 */ 2153 *raw_name = 0; 2154 name_len = 0; 2155 inchp = name; 2156 outchp = raw_name; 2157 while (*inchp) { 2158 *outchp++ = (uint16_t) (*inchp++); 2159 name_len++; 2160 } 2161 2162 if ((chsp->type == 0) && (strcmp((char *) chsp->inf, "OSTA Compressed Unicode") == 0)) { 2163 udf_chars = udf_CompressUnicode(name_len, 8, (unicode_t *) raw_name, (byte *) result); 2164 } else { 2165 /* XXX assume 8bit char length byte latin-1 */ 2166 *result++ = 8; udf_chars = 1; 2167 strncpy(result, name + 1, strlen(name+1)); 2168 udf_chars += strlen(name); 2169 } 2170 *result_len = udf_chars; 2171 free(raw_name, M_UDFTEMP); 2172 } 2173 2174 /* --------------------------------------------------------------------- */ 2175 2176 /* 2177 * Timestamp to timespec conversion code is taken with small modifications 2178 * from FreeBSDs /sys/fs/udf by Scott Long <scottl@freebsd.org>. Added with 2179 * permission from Scott. 2180 */ 2181 2182 static int mon_lens[2][12] = { 2183 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 2184 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 2185 }; 2186 2187 2188 static int 2189 udf_isaleapyear(int year) 2190 { 2191 int i; 2192 2193 i = (year % 4) ? 0 : 1; 2194 i &= (year % 100) ? 1 : 0; 2195 i |= (year % 400) ? 0 : 1; 2196 2197 return i; 2198 } 2199 2200 2201 void 2202 udf_timestamp_to_timespec(struct udf_mount *ump, 2203 struct timestamp *timestamp, 2204 struct timespec *timespec) 2205 { 2206 uint32_t usecs, secs, nsecs; 2207 uint16_t tz; 2208 int i, lpyear, daysinyear, year; 2209 2210 timespec->tv_sec = secs = 0; 2211 timespec->tv_nsec = nsecs = 0; 2212 2213 /* 2214 * DirectCD seems to like using bogus year values. 2215 * 2216 * Distrust time->month especially, since it will be used for an array 2217 * index. 2218 */ 2219 year = udf_rw16(timestamp->year); 2220 if ((year < 1970) || (timestamp->month > 12)) { 2221 return; 2222 } 2223 2224 /* Calculate the time and day 2225 * Day is 1-31, Month is 1-12 2226 */ 2227 2228 usecs = timestamp->usec + 2229 100*timestamp->hund_usec + 10000*timestamp->centisec; 2230 nsecs = usecs * 1000; 2231 secs = timestamp->second; 2232 secs += timestamp->minute * 60; 2233 secs += timestamp->hour * 3600; 2234 secs += (timestamp->day-1) * 3600 * 24; 2235 2236 /* Calclulate the month */ 2237 lpyear = udf_isaleapyear(year); 2238 for (i = 1; i < timestamp->month; i++) 2239 secs += mon_lens[lpyear][i-1] * 3600 * 24; 2240 2241 for (i = 1970; i < year; i++) { 2242 daysinyear = udf_isaleapyear(i) + 365 ; 2243 secs += daysinyear * 3600 * 24; 2244 } 2245 2246 /* 2247 * Calculate the time zone. The timezone is 12 bit signed 2's 2248 * compliment, so we gotta do some extra magic to handle it right. 2249 */ 2250 tz = udf_rw16(timestamp->type_tz); 2251 tz &= 0x0fff; /* only lower 12 bits are significant */ 2252 if (tz & 0x0800) /* sign extention */ 2253 tz |= 0xf000; 2254 2255 /* TODO check timezone conversion */ 2256 /* check if we are specified a timezone to convert */ 2257 if (udf_rw16(timestamp->type_tz) & 0x1000) { 2258 if ((int16_t) tz != -2047) 2259 secs -= (int16_t) tz * 60; 2260 } else { 2261 secs -= ump->mount_args.gmtoff; 2262 } 2263 2264 timespec->tv_sec = secs; 2265 timespec->tv_nsec = nsecs; 2266 } 2267 2268 /* --------------------------------------------------------------------- */ 2269 2270 /* 2271 * Attribute and filetypes converters with get/set pairs 2272 */ 2273 2274 uint32_t 2275 udf_getaccessmode(struct udf_node *udf_node) 2276 { 2277 struct file_entry *fe; 2278 struct extfile_entry *efe; 2279 uint32_t udf_perm, icbftype; 2280 uint32_t mode, ftype; 2281 uint16_t icbflags; 2282 2283 if (udf_node->fe) { 2284 fe = udf_node->fe; 2285 udf_perm = udf_rw32(fe->perm); 2286 icbftype = fe->icbtag.file_type; 2287 icbflags = udf_rw16(fe->icbtag.flags); 2288 } else { 2289 assert(udf_node->efe); 2290 efe = udf_node->efe; 2291 udf_perm = udf_rw32(efe->perm); 2292 icbftype = efe->icbtag.file_type; 2293 icbflags = udf_rw16(efe->icbtag.flags); 2294 } 2295 2296 mode = udf_perm_to_unix_mode(udf_perm); 2297 ftype = udf_icb_to_unix_filetype(icbftype); 2298 2299 /* set suid, sgid, sticky from flags in fe/efe */ 2300 if (icbflags & UDF_ICB_TAG_FLAGS_SETUID) 2301 mode |= S_ISUID; 2302 if (icbflags & UDF_ICB_TAG_FLAGS_SETGID) 2303 mode |= S_ISGID; 2304 if (icbflags & UDF_ICB_TAG_FLAGS_STICKY) 2305 mode |= S_ISVTX; 2306 2307 return mode | ftype; 2308 } 2309 2310 /* --------------------------------------------------------------------- */ 2311 2312 /* 2313 * Directory read and manipulation functions 2314 */ 2315 2316 int 2317 udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, 2318 struct long_ad *icb_loc) 2319 { 2320 struct udf_node *dir_node = VTOI(vp); 2321 struct file_entry *fe; 2322 struct extfile_entry *efe; 2323 struct fileid_desc *fid; 2324 struct dirent dirent; 2325 uint64_t file_size, diroffset; 2326 uint32_t lb_size; 2327 int found, error; 2328 2329 /* get directory filesize */ 2330 if (dir_node->fe) { 2331 fe = dir_node->fe; 2332 file_size = udf_rw64(fe->inf_len); 2333 } else { 2334 assert(dir_node->efe); 2335 efe = dir_node->efe; 2336 file_size = udf_rw64(efe->inf_len); 2337 } 2338 2339 /* allocate temporary space for fid */ 2340 lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 2341 fid = malloc(lb_size, M_TEMP, M_WAITOK); 2342 2343 found = 0; 2344 diroffset = dir_node->last_diroffset; 2345 while (!found) { 2346 /* if not found in this track, turn trough zero */ 2347 if (diroffset >= file_size) 2348 diroffset = 0; 2349 2350 /* transfer a new fid/dirent */ 2351 error = udf_read_fid_stream(vp, &diroffset, fid, &dirent); 2352 if (error) 2353 break; 2354 2355 /* skip deleted entries */ 2356 if ((fid->file_char & UDF_FILE_CHAR_DEL) == 0) { 2357 if ((strlen(dirent.d_name) == namelen) && 2358 (strncmp(dirent.d_name, name, namelen) == 0)) { 2359 found = 1; 2360 *icb_loc = fid->icb; 2361 } 2362 } 2363 2364 if (diroffset == dir_node->last_diroffset) { 2365 /* we have cycled */ 2366 break; 2367 } 2368 } 2369 free(fid, M_TEMP); 2370 dir_node->last_diroffset = diroffset; 2371 2372 return found; 2373 } 2374 2375 /* --------------------------------------------------------------------- */ 2376 2377 /* 2378 * Read one fid and process it into a dirent and advance to the next (*fid) 2379 * has to be allocated a logical block in size, (*dirent) struct dirent length 2380 */ 2381 2382 int 2383 udf_read_fid_stream(struct vnode *vp, uint64_t *offset, 2384 struct fileid_desc *fid, struct dirent *dirent) 2385 { 2386 struct udf_node *dir_node = VTOI(vp); 2387 struct udf_mount *ump = dir_node->ump; 2388 struct file_entry *fe; 2389 struct extfile_entry *efe; 2390 struct uio dir_uio; 2391 struct iovec dir_iovec; 2392 uint32_t entry_length, lb_size; 2393 uint64_t file_size; 2394 char *fid_name; 2395 int enough, error; 2396 2397 assert(fid); 2398 assert(dirent); 2399 assert(dir_node); 2400 assert(offset); 2401 assert(*offset != 1); 2402 2403 DPRINTF(FIDS, ("read_fid_stream called\n")); 2404 /* check if we're past the end of the directory */ 2405 if (dir_node->fe) { 2406 fe = dir_node->fe; 2407 file_size = udf_rw64(fe->inf_len); 2408 } else { 2409 assert(dir_node->efe); 2410 efe = dir_node->efe; 2411 file_size = udf_rw64(efe->inf_len); 2412 } 2413 if (*offset >= file_size) 2414 return EINVAL; 2415 2416 /* get maximum length of FID descriptor */ 2417 lb_size = udf_rw32(ump->logical_vol->lb_size); 2418 2419 /* initialise return values */ 2420 entry_length = 0; 2421 memset(dirent, 0, sizeof(struct dirent)); 2422 memset(fid, 0, lb_size); 2423 2424 /* TODO use vn_rdwr instead of creating our own uio */ 2425 /* read part of the directory */ 2426 memset(&dir_uio, 0, sizeof(struct uio)); 2427 dir_uio.uio_rw = UIO_READ; /* read into this space */ 2428 dir_uio.uio_iovcnt = 1; 2429 dir_uio.uio_iov = &dir_iovec; 2430 UIO_SETUP_SYSSPACE(&dir_uio); 2431 dir_iovec.iov_base = fid; 2432 dir_iovec.iov_len = lb_size; 2433 dir_uio.uio_offset = *offset; 2434 2435 /* limit length of read in piece */ 2436 dir_uio.uio_resid = MIN(file_size - (*offset), lb_size); 2437 2438 /* read the part into the fid space */ 2439 error = VOP_READ(vp, &dir_uio, IO_ALTSEMANTICS, NOCRED); 2440 if (error) 2441 return error; 2442 2443 /* 2444 * Check if we got a whole descriptor. 2445 * XXX Try to `resync' directory stream when something is very wrong. 2446 * 2447 */ 2448 enough = (dir_uio.uio_offset - (*offset) >= UDF_FID_SIZE); 2449 if (!enough) { 2450 /* short dir ... */ 2451 return EIO; 2452 } 2453 2454 /* check if our FID header is OK */ 2455 error = udf_check_tag(fid); 2456 DPRINTFIF(FIDS, error, ("read fids: tag check failed\n")); 2457 if (!error) { 2458 if (udf_rw16(fid->tag.id) != TAGID_FID) 2459 error = ENOENT; 2460 } 2461 DPRINTFIF(FIDS, !error, ("\ttag checked ok: got TAGID_FID\n")); 2462 2463 /* check for length */ 2464 if (!error) { 2465 entry_length = udf_fidsize(fid, lb_size); 2466 enough = (dir_uio.uio_offset - (*offset) >= entry_length); 2467 } 2468 DPRINTFIF(FIDS, !error, ("\tentry_length = %d, enough = %s\n", 2469 entry_length, enough?"yes":"no")); 2470 2471 if (!enough) { 2472 /* short dir ... bomb out */ 2473 return EIO; 2474 } 2475 2476 /* check FID contents */ 2477 if (!error) { 2478 error = udf_check_tag_payload((union dscrptr *) fid, lb_size); 2479 DPRINTF(FIDS, ("\tpayload checked ok\n")); 2480 } 2481 if (error) { 2482 /* note that is sometimes a bit quick to report */ 2483 printf("BROKEN DIRECTORY ENTRY\n"); 2484 /* RESYNC? */ 2485 /* TODO: use udf_resync_fid_stream */ 2486 return EIO; 2487 } 2488 DPRINTF(FIDS, ("\tinterpret FID\n")); 2489 2490 /* we got a whole and valid descriptor! */ 2491 2492 /* create resulting dirent structure */ 2493 fid_name = (char *) fid->data + udf_rw16(fid->l_iu); 2494 udf_to_unix_name(dirent->d_name, 2495 fid_name, fid->l_fi, &ump->logical_vol->desc_charset); 2496 2497 /* '..' has no name, so provide one */ 2498 if (fid->file_char & UDF_FILE_CHAR_PAR) 2499 strcpy(dirent->d_name, ".."); 2500 2501 dirent->d_fileno = udf_calchash(&fid->icb); /* inode hash XXX */ 2502 dirent->d_namlen = strlen(dirent->d_name); 2503 dirent->d_reclen = _DIRENT_SIZE(dirent); 2504 2505 /* 2506 * Note that its not worth trying to go for the filetypes now... its 2507 * too expensive too 2508 */ 2509 dirent->d_type = DT_UNKNOWN; 2510 2511 /* initial guess for filetype we can make */ 2512 if (fid->file_char & UDF_FILE_CHAR_DIR) 2513 dirent->d_type = DT_DIR; 2514 2515 /* advance */ 2516 *offset += entry_length; 2517 2518 return error; 2519 } 2520 2521 /* --------------------------------------------------------------------- */ 2522 2523 /* 2524 * block based file reading and writing 2525 */ 2526 2527 static int 2528 udf_read_internal(struct udf_node *node, uint8_t *blob) 2529 { 2530 struct udf_mount *ump; 2531 struct file_entry *fe; 2532 struct extfile_entry *efe; 2533 uint64_t inflen; 2534 uint32_t sector_size; 2535 uint8_t *pos; 2536 int icbflags, addr_type; 2537 2538 /* shut up gcc */ 2539 inflen = addr_type = icbflags = 0; 2540 pos = NULL; 2541 2542 /* get extent and do some paranoia checks */ 2543 ump = node->ump; 2544 sector_size = ump->discinfo.sector_size; 2545 2546 fe = node->fe; 2547 efe = node->efe; 2548 if (fe) { 2549 inflen = udf_rw64(fe->inf_len); 2550 pos = &fe->data[0] + udf_rw32(fe->l_ea); 2551 icbflags = udf_rw16(fe->icbtag.flags); 2552 } 2553 if (efe) { 2554 inflen = udf_rw64(efe->inf_len); 2555 pos = &efe->data[0] + udf_rw32(efe->l_ea); 2556 icbflags = udf_rw16(efe->icbtag.flags); 2557 } 2558 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2559 2560 assert(addr_type == UDF_ICB_INTERN_ALLOC); 2561 assert(inflen < sector_size); 2562 2563 /* copy out info */ 2564 memset(blob, 0, sector_size); 2565 memcpy(blob, pos, inflen); 2566 2567 return 0; 2568 } 2569 2570 /* --------------------------------------------------------------------- */ 2571 2572 /* 2573 * Read file extent reads an extent specified in sectors from the file. It is 2574 * sector based; i.e. no `fancy' offsets. 2575 */ 2576 2577 int 2578 udf_read_file_extent(struct udf_node *node, 2579 uint32_t from, uint32_t sectors, 2580 uint8_t *blob) 2581 { 2582 struct buf buf; 2583 uint32_t sector_size; 2584 2585 BUF_INIT(&buf); 2586 2587 sector_size = node->ump->discinfo.sector_size; 2588 2589 buf.b_bufsize = sectors * sector_size; 2590 buf.b_data = blob; 2591 buf.b_bcount = buf.b_bufsize; 2592 buf.b_resid = buf.b_bcount; 2593 buf.b_flags = B_BUSY | B_READ; 2594 buf.b_vp = node->vnode; 2595 buf.b_proc = NULL; 2596 2597 buf.b_blkno = from; 2598 buf.b_lblkno = 0; 2599 BIO_SETPRIO(&buf, BPRIO_TIMELIMITED); 2600 2601 udf_read_filebuf(node, &buf); 2602 return biowait(&buf); 2603 } 2604 2605 2606 /* --------------------------------------------------------------------- */ 2607 2608 /* 2609 * Read file extent in the buffer. 2610 * 2611 * The splitup of the extent into seperate request-buffers is to minimise 2612 * copying around as much as possible. 2613 */ 2614 2615 2616 /* maximum of 128 translations (!) (64 kb in 512 byte sectors) */ 2617 #define FILEBUFSECT 128 2618 2619 void 2620 udf_read_filebuf(struct udf_node *node, struct buf *buf) 2621 { 2622 struct buf *nestbuf; 2623 uint64_t *mapping; 2624 uint64_t run_start; 2625 uint32_t sector_size; 2626 uint32_t buf_offset, sector, rbuflen, rblk; 2627 uint8_t *buf_pos; 2628 int error, run_length; 2629 2630 uint32_t from; 2631 uint32_t sectors; 2632 2633 sector_size = node->ump->discinfo.sector_size; 2634 2635 from = buf->b_blkno; 2636 sectors = buf->b_bcount / sector_size; 2637 2638 /* assure we have enough translation slots */ 2639 KASSERT(buf->b_bcount / sector_size <= FILEBUFSECT); 2640 KASSERT(MAXPHYS / sector_size <= FILEBUFSECT); 2641 2642 if (sectors > FILEBUFSECT) { 2643 printf("udf_read_filebuf: implementation limit on bufsize\n"); 2644 buf->b_error = EIO; 2645 buf->b_flags |= B_ERROR; 2646 biodone(buf); 2647 return; 2648 } 2649 2650 mapping = malloc(sizeof(*mapping) * FILEBUFSECT, M_TEMP, M_WAITOK); 2651 2652 error = 0; 2653 DPRINTF(READ, ("\ttranslate %d-%d\n", from, sectors)); 2654 error = udf_translate_file_extent(node, from, sectors, mapping); 2655 if (error) { 2656 buf->b_error = error; 2657 buf->b_flags |= B_ERROR; 2658 biodone(buf); 2659 goto out; 2660 } 2661 DPRINTF(READ, ("\ttranslate extent went OK\n")); 2662 2663 /* pre-check if internal or parts are zero */ 2664 if (*mapping == UDF_TRANS_INTERN) { 2665 error = udf_read_internal(node, (uint8_t *) buf->b_data); 2666 if (error) { 2667 buf->b_error = error; 2668 buf->b_flags |= B_ERROR; 2669 } 2670 biodone(buf); 2671 goto out; 2672 } 2673 DPRINTF(READ, ("\tnot intern\n")); 2674 2675 /* request read-in of data from disc sheduler */ 2676 buf->b_resid = buf->b_bcount; 2677 for (sector = 0; sector < sectors; sector++) { 2678 buf_offset = sector * sector_size; 2679 buf_pos = (uint8_t *) buf->b_data + buf_offset; 2680 DPRINTF(READ, ("\tprocessing rel sector %d\n", sector)); 2681 2682 switch (mapping[sector]) { 2683 case UDF_TRANS_UNMAPPED: 2684 case UDF_TRANS_ZERO: 2685 /* copy zero sector */ 2686 memset(buf_pos, 0, sector_size); 2687 DPRINTF(READ, ("\treturning zero sector\n")); 2688 nestiobuf_done(buf, sector_size, 0); 2689 break; 2690 default : 2691 DPRINTF(READ, ("\tread sector " 2692 "%"PRIu64"\n", mapping[sector])); 2693 2694 run_start = mapping[sector]; 2695 run_length = 1; 2696 while (sector < sectors-1) { 2697 if (mapping[sector+1] != mapping[sector]+1) 2698 break; 2699 run_length++; 2700 sector++; 2701 } 2702 2703 /* 2704 * nest an iobuf and mark it for async reading. Since 2705 * we're using nested buffers, they can't be cached by 2706 * design. 2707 */ 2708 rbuflen = run_length * sector_size; 2709 rblk = run_start * (sector_size/DEV_BSIZE); 2710 2711 nestbuf = getiobuf(); 2712 nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen); 2713 /* nestbuf is B_ASYNC */ 2714 2715 /* CD shedules on raw blkno */ 2716 nestbuf->b_blkno = rblk; 2717 nestbuf->b_proc = NULL; 2718 nestbuf->b_cylinder = 0; 2719 nestbuf->b_rawblkno = rblk; 2720 VOP_STRATEGY(node->ump->devvp, nestbuf); 2721 } 2722 } 2723 out: 2724 DPRINTF(READ, ("\tend of read_filebuf\n")); 2725 free(mapping, M_TEMP); 2726 return; 2727 } 2728 #undef FILEBUFSECT 2729 2730 2731 /* --------------------------------------------------------------------- */ 2732 2733 /* 2734 * Translate an extent (in sectors) into sector numbers; used for read and 2735 * write operations. DOESNT't check extents. 2736 */ 2737 2738 int 2739 udf_translate_file_extent(struct udf_node *node, 2740 uint32_t from, uint32_t pages, 2741 uint64_t *map) 2742 { 2743 struct udf_mount *ump; 2744 struct file_entry *fe; 2745 struct extfile_entry *efe; 2746 struct short_ad *s_ad; 2747 struct long_ad *l_ad, t_ad; 2748 uint64_t transsec; 2749 uint32_t sector_size, transsec32; 2750 uint32_t overlap, translen; 2751 uint32_t vpart_num, lb_num, len, alloclen; 2752 uint8_t *pos; 2753 int error, flags, addr_type, icblen, icbflags; 2754 2755 if (!node) 2756 return ENOENT; 2757 2758 /* shut up gcc */ 2759 alloclen = addr_type = icbflags = 0; 2760 pos = NULL; 2761 2762 /* do the work */ 2763 ump = node->ump; 2764 sector_size = ump->discinfo.sector_size; 2765 fe = node->fe; 2766 efe = node->efe; 2767 if (fe) { 2768 alloclen = udf_rw32(fe->l_ad); 2769 pos = &fe->data[0] + udf_rw32(fe->l_ea); 2770 icbflags = udf_rw16(fe->icbtag.flags); 2771 } 2772 if (efe) { 2773 alloclen = udf_rw32(efe->l_ad); 2774 pos = &efe->data[0] + udf_rw32(efe->l_ea); 2775 icbflags = udf_rw16(efe->icbtag.flags); 2776 } 2777 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2778 2779 DPRINTF(TRANSLATE, ("udf trans: alloc_len = %d, addr_type %d, " 2780 "fe %p, efe %p\n", alloclen, addr_type, fe, efe)); 2781 2782 vpart_num = udf_rw16(node->loc.loc.part_num); 2783 lb_num = len = icblen = 0; /* shut up gcc */ 2784 while (pages && alloclen) { 2785 DPRINTF(TRANSLATE, ("\taddr_type %d\n", addr_type)); 2786 switch (addr_type) { 2787 case UDF_ICB_INTERN_ALLOC : 2788 /* TODO check extents? */ 2789 *map = UDF_TRANS_INTERN; 2790 return 0; 2791 case UDF_ICB_SHORT_ALLOC : 2792 icblen = sizeof(struct short_ad); 2793 s_ad = (struct short_ad *) pos; 2794 len = udf_rw32(s_ad->len); 2795 lb_num = udf_rw32(s_ad->lb_num); 2796 break; 2797 case UDF_ICB_LONG_ALLOC : 2798 icblen = sizeof(struct long_ad); 2799 l_ad = (struct long_ad *) pos; 2800 len = udf_rw32(l_ad->len); 2801 lb_num = udf_rw32(l_ad->loc.lb_num); 2802 vpart_num = udf_rw16(l_ad->loc.part_num); 2803 DPRINTFIF(TRANSLATE, 2804 (l_ad->impl.im_used.flags & 2805 UDF_ADIMP_FLAGS_EXTENT_ERASED), 2806 ("UDF: got an `extent erased' flag in long_ad\n")); 2807 break; 2808 default: 2809 /* can't be here */ 2810 return EINVAL; /* for sure */ 2811 } 2812 2813 /* process extent */ 2814 flags = UDF_EXT_FLAGS(len); 2815 len = UDF_EXT_LEN(len); 2816 2817 overlap = (len + sector_size -1) / sector_size; 2818 if (from) { 2819 if (from > overlap) { 2820 from -= overlap; 2821 overlap = 0; 2822 } else { 2823 lb_num += from; /* advance in extent */ 2824 overlap -= from; 2825 from = 0; 2826 } 2827 } 2828 2829 overlap = MIN(overlap, pages); 2830 while (overlap) { 2831 switch (flags) { 2832 case UDF_EXT_REDIRECT : 2833 /* no support for allocation extentions yet */ 2834 /* TODO support for allocation extention */ 2835 return ENOENT; 2836 case UDF_EXT_FREED : 2837 case UDF_EXT_FREE : 2838 transsec = UDF_TRANS_ZERO; 2839 translen = overlap; 2840 while (overlap && pages && translen) { 2841 *map++ = transsec; 2842 lb_num++; 2843 overlap--; pages--; translen--; 2844 } 2845 break; 2846 case UDF_EXT_ALLOCATED : 2847 t_ad.loc.lb_num = udf_rw32(lb_num); 2848 t_ad.loc.part_num = udf_rw16(vpart_num); 2849 error = udf_translate_vtop(ump, 2850 &t_ad, &transsec32, &translen); 2851 transsec = transsec32; 2852 if (error) 2853 return error; 2854 while (overlap && pages && translen) { 2855 *map++ = transsec; 2856 lb_num++; transsec++; 2857 overlap--; pages--; translen--; 2858 } 2859 break; 2860 } 2861 } 2862 pos += icblen; 2863 alloclen -= icblen; 2864 } 2865 return 0; 2866 } 2867 2868 /* --------------------------------------------------------------------- */ 2869 2870