1 /* $NetBSD: udf_subr.c,v 1.19 2006/09/28 19:57:26 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.19 2006/09/28 19:57:26 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 if (error) 1367 return ENOENT; 1368 break; 1369 case UDF_VTOP_TYPE_META : 1370 /* TODO load metafile and metabitmapfile FE/EFEs */ 1371 return ENOENT; 1372 default: 1373 break; 1374 } 1375 pmap_size = pmap_pos[1]; 1376 pmap_pos += pmap_size; 1377 } 1378 1379 return 0; 1380 } 1381 1382 /* --------------------------------------------------------------------- */ 1383 1384 int 1385 udf_read_rootdirs(struct udf_mount *ump, struct udf_args *args) 1386 { 1387 struct udf_node *rootdir_node, *streamdir_node; 1388 union dscrptr *dscr; 1389 struct long_ad fsd_loc, *dir_loc; 1390 uint32_t lb_num, dummy; 1391 uint32_t fsd_len; 1392 int dscr_type; 1393 int error; 1394 1395 /* TODO implement FSD reading in seperate function like integrity? */ 1396 /* get fileset descriptor sequence */ 1397 fsd_loc = ump->logical_vol->lv_fsd_loc; 1398 fsd_len = udf_rw32(fsd_loc.len); 1399 1400 dscr = NULL; 1401 error = 0; 1402 while (fsd_len || error) { 1403 DPRINTF(VOLUMES, ("fsd_len = %d\n", fsd_len)); 1404 /* translate fsd_loc to lb_num */ 1405 error = udf_translate_vtop(ump, &fsd_loc, &lb_num, &dummy); 1406 if (error) 1407 break; 1408 DPRINTF(VOLUMES, ("Reading FSD at lb %d\n", lb_num)); 1409 error = udf_read_descriptor(ump, lb_num, M_UDFVOLD, &dscr); 1410 /* end markers */ 1411 if (error || (dscr == NULL)) 1412 break; 1413 1414 /* analyse */ 1415 dscr_type = udf_rw16(dscr->tag.id); 1416 if (dscr_type == TAGID_TERM) 1417 break; 1418 if (dscr_type != TAGID_FSD) { 1419 free(dscr, M_UDFVOLD); 1420 return ENOENT; 1421 } 1422 1423 /* 1424 * TODO check for multiple fileset descriptors; its only 1425 * picking the last now. Also check for FSD 1426 * correctness/interpretability 1427 */ 1428 1429 /* update */ 1430 if (ump->fileset_desc) { 1431 free(ump->fileset_desc, M_UDFVOLD); 1432 } 1433 ump->fileset_desc = &dscr->fsd; 1434 dscr = NULL; 1435 1436 /* continue to the next fsd */ 1437 fsd_len -= ump->discinfo.sector_size; 1438 fsd_loc.loc.lb_num = udf_rw32(udf_rw32(fsd_loc.loc.lb_num)+1); 1439 1440 /* follow up to fsd->next_ex (long_ad) if its not null */ 1441 if (udf_rw32(ump->fileset_desc->next_ex.len)) { 1442 DPRINTF(VOLUMES, ("follow up FSD extent\n")); 1443 fsd_loc = ump->fileset_desc->next_ex; 1444 fsd_len = udf_rw32(ump->fileset_desc->next_ex.len); 1445 } 1446 } 1447 if (dscr) 1448 free(dscr, M_UDFVOLD); 1449 1450 /* there has to be one */ 1451 if (ump->fileset_desc == NULL) 1452 return ENOENT; 1453 1454 DPRINTF(VOLUMES, ("FSD read in fine\n")); 1455 1456 /* 1457 * Now the FSD is known, read in the rootdirectory and if one exists, 1458 * the system stream dir. Some files in the system streamdir are not 1459 * wanted in this implementation since they are not maintained. If 1460 * writing is enabled we'll delete these files if they exist. 1461 */ 1462 1463 rootdir_node = streamdir_node = NULL; 1464 dir_loc = NULL; 1465 1466 /* try to read in the rootdir */ 1467 dir_loc = &ump->fileset_desc->rootdir_icb; 1468 error = udf_get_node(ump, dir_loc, &rootdir_node); 1469 if (error) 1470 return ENOENT; 1471 1472 /* aparently it read in fine */ 1473 1474 /* 1475 * Try the system stream directory; not very likely in the ones we 1476 * test, but for completeness. 1477 */ 1478 dir_loc = &ump->fileset_desc->streamdir_icb; 1479 if (udf_rw32(dir_loc->len)) { 1480 error = udf_get_node(ump, dir_loc, &streamdir_node); 1481 if (error) 1482 printf("udf mount: streamdir defined but ignored\n"); 1483 if (!error) { 1484 /* 1485 * TODO process streamdir `baddies' i.e. files we dont 1486 * want if R/W 1487 */ 1488 } 1489 } 1490 1491 DPRINTF(VOLUMES, ("Rootdir(s) read in fine\n")); 1492 1493 /* release the vnodes again; they'll be auto-recycled later */ 1494 if (streamdir_node) { 1495 vput(streamdir_node->vnode); 1496 } 1497 if (rootdir_node) { 1498 vput(rootdir_node->vnode); 1499 } 1500 1501 return 0; 1502 } 1503 1504 /* --------------------------------------------------------------------- */ 1505 1506 int 1507 udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc, 1508 uint32_t *lb_numres, uint32_t *extres) 1509 { 1510 struct part_desc *pdesc; 1511 struct spare_map_entry *sme; 1512 uint32_t *trans; 1513 uint32_t lb_num, lb_rel, lb_packet; 1514 int rel, vpart, part; 1515 1516 assert(ump && icb_loc && lb_numres); 1517 1518 vpart = udf_rw16(icb_loc->loc.part_num); 1519 lb_num = udf_rw32(icb_loc->loc.lb_num); 1520 if (vpart < 0 || vpart > UDF_VTOP_RAWPART) 1521 return EINVAL; 1522 1523 switch (ump->vtop_tp[vpart]) { 1524 case UDF_VTOP_TYPE_RAW : 1525 /* 1:1 to the end of the device */ 1526 *lb_numres = lb_num; 1527 *extres = INT_MAX; 1528 return 0; 1529 case UDF_VTOP_TYPE_PHYS : 1530 /* transform into its disc logical block */ 1531 part = ump->vtop[vpart]; 1532 pdesc = ump->partitions[part]; 1533 if (lb_num > udf_rw32(pdesc->part_len)) 1534 return EINVAL; 1535 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1536 1537 /* extent from here to the end of the partition */ 1538 *extres = udf_rw32(pdesc->part_len) - lb_num; 1539 return 0; 1540 case UDF_VTOP_TYPE_VIRT : 1541 /* only maps one sector, lookup in VAT */ 1542 if (lb_num >= ump->vat_entries) /* XXX > or >= ? */ 1543 return EINVAL; 1544 1545 /* lookup in virtual allocation table */ 1546 trans = (uint32_t *) (ump->vat_table + ump->vat_offset); 1547 lb_num = udf_rw32(trans[lb_num]); 1548 1549 /* transform into its disc logical block */ 1550 part = ump->vtop[vpart]; 1551 pdesc = ump->partitions[part]; 1552 if (lb_num > udf_rw32(pdesc->part_len)) 1553 return EINVAL; 1554 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1555 1556 /* just one logical block */ 1557 *extres = 1; 1558 return 0; 1559 case UDF_VTOP_TYPE_SPARABLE : 1560 /* check if the packet containing the lb_num is remapped */ 1561 lb_packet = lb_num / ump->sparable_packet_len; 1562 lb_rel = lb_num % ump->sparable_packet_len; 1563 1564 for (rel = 0; rel < udf_rw16(ump->sparing_table->rt_l); rel++) { 1565 sme = &ump->sparing_table->entries[rel]; 1566 if (lb_packet == udf_rw32(sme->org)) { 1567 /* NOTE maps to absolute disc logical block! */ 1568 *lb_numres = udf_rw32(sme->map) + lb_rel; 1569 *extres = ump->sparable_packet_len - lb_rel; 1570 return 0; 1571 } 1572 } 1573 1574 /* transform into its disc logical block */ 1575 part = ump->vtop[vpart]; 1576 pdesc = ump->partitions[part]; 1577 if (lb_num > udf_rw32(pdesc->part_len)) 1578 return EINVAL; 1579 *lb_numres = lb_num + udf_rw32(pdesc->start_loc); 1580 1581 /* rest of block */ 1582 *extres = ump->sparable_packet_len - lb_rel; 1583 return 0; 1584 case UDF_VTOP_TYPE_META : 1585 default: 1586 printf("UDF vtop translation scheme %d unimplemented yet\n", 1587 ump->vtop_tp[vpart]); 1588 } 1589 1590 return EINVAL; 1591 } 1592 1593 /* --------------------------------------------------------------------- */ 1594 1595 /* To make absolutely sure we are NOT returning zero, add one :) */ 1596 1597 long 1598 udf_calchash(struct long_ad *icbptr) 1599 { 1600 /* ought to be enough since each mountpoint has its own chain */ 1601 return udf_rw32(icbptr->loc.lb_num) + 1; 1602 } 1603 1604 /* --------------------------------------------------------------------- */ 1605 1606 static struct udf_node * 1607 udf_hashget(struct udf_mount *ump, struct long_ad *icbptr) 1608 { 1609 struct udf_node *unp; 1610 struct vnode *vp; 1611 uint32_t hashline; 1612 1613 loop: 1614 simple_lock(&ump->ihash_slock); 1615 1616 hashline = udf_calchash(icbptr) & UDF_INODE_HASHMASK; 1617 LIST_FOREACH(unp, &ump->udf_nodes[hashline], hashchain) { 1618 assert(unp); 1619 if (unp->loc.loc.lb_num == icbptr->loc.lb_num && 1620 unp->loc.loc.part_num == icbptr->loc.part_num) { 1621 vp = unp->vnode; 1622 assert(vp); 1623 simple_lock(&vp->v_interlock); 1624 simple_unlock(&ump->ihash_slock); 1625 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) 1626 goto loop; 1627 return unp; 1628 } 1629 } 1630 simple_unlock(&ump->ihash_slock); 1631 1632 return NULL; 1633 } 1634 1635 /* --------------------------------------------------------------------- */ 1636 1637 static void 1638 udf_hashins(struct udf_node *unp) 1639 { 1640 struct udf_mount *ump; 1641 uint32_t hashline; 1642 1643 ump = unp->ump; 1644 simple_lock(&ump->ihash_slock); 1645 1646 hashline = udf_calchash(&unp->loc) & UDF_INODE_HASHMASK; 1647 LIST_INSERT_HEAD(&ump->udf_nodes[hashline], unp, hashchain); 1648 1649 simple_unlock(&ump->ihash_slock); 1650 } 1651 1652 /* --------------------------------------------------------------------- */ 1653 1654 static void 1655 udf_hashrem(struct udf_node *unp) 1656 { 1657 struct udf_mount *ump; 1658 1659 ump = unp->ump; 1660 simple_lock(&ump->ihash_slock); 1661 1662 LIST_REMOVE(unp, hashchain); 1663 1664 simple_unlock(&ump->ihash_slock); 1665 } 1666 1667 /* --------------------------------------------------------------------- */ 1668 1669 int 1670 udf_dispose_locked_node(struct udf_node *node) 1671 { 1672 if (!node) 1673 return 0; 1674 if (node->vnode) 1675 VOP_UNLOCK(node->vnode, 0); 1676 return udf_dispose_node(node); 1677 } 1678 1679 /* --------------------------------------------------------------------- */ 1680 1681 int 1682 udf_dispose_node(struct udf_node *node) 1683 { 1684 struct vnode *vp; 1685 1686 DPRINTF(NODE, ("udf_dispose_node called on node %p\n", node)); 1687 if (!node) { 1688 DPRINTF(NODE, ("UDF: Dispose node on node NULL, ignoring\n")); 1689 return 0; 1690 } 1691 1692 vp = node->vnode; 1693 1694 /* TODO extended attributes and streamdir */ 1695 1696 /* remove from our hash lookup table */ 1697 udf_hashrem(node); 1698 1699 /* dissociate our udf_node from the vnode */ 1700 vp->v_data = NULL; 1701 1702 /* free associated memory and the node itself */ 1703 if (node->fe) 1704 pool_put(node->ump->desc_pool, node->fe); 1705 if (node->efe) 1706 pool_put(node->ump->desc_pool, node->efe); 1707 pool_put(&udf_node_pool, node); 1708 1709 return 0; 1710 } 1711 1712 /* --------------------------------------------------------------------- */ 1713 1714 /* 1715 * Genfs interfacing 1716 * 1717 * static const struct genfs_ops udffs_genfsops = { 1718 * .gop_size = genfs_size, 1719 * size of transfers 1720 * .gop_alloc = udf_gop_alloc, 1721 * unknown 1722 * .gop_write = genfs_gop_write, 1723 * putpages interface code 1724 * .gop_markupdate = udf_gop_markupdate, 1725 * set update/modify flags etc. 1726 * } 1727 */ 1728 1729 /* 1730 * Genfs interface. These four functions are the only ones defined though not 1731 * documented... great.... why is chosen for the `.' initialisers i dont know 1732 * but other filingsystems seem to use it this way. 1733 */ 1734 1735 static int 1736 udf_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, 1737 kauth_cred_t cred) 1738 { 1739 return 0; 1740 } 1741 1742 1743 static void 1744 udf_gop_markupdate(struct vnode *vp, int flags) 1745 { 1746 struct udf_node *udf_node = VTOI(vp); 1747 u_long mask; 1748 1749 udf_node = udf_node; /* shut up gcc */ 1750 1751 mask = 0; 1752 #ifdef notyet 1753 if ((flags & GOP_UPDATE_ACCESSED) != 0) { 1754 mask = UDF_SET_ACCESS; 1755 } 1756 if ((flags & GOP_UPDATE_MODIFIED) != 0) { 1757 mask |= UDF_SET_UPDATE; 1758 } 1759 if (mask) { 1760 udf_node->update_flag |= mask; 1761 } 1762 #endif 1763 /* msdosfs doesn't do it, but shouldn't we update the times here? */ 1764 } 1765 1766 1767 static const struct genfs_ops udf_genfsops = { 1768 .gop_size = genfs_size, 1769 .gop_alloc = udf_gop_alloc, 1770 .gop_write = genfs_gop_write, 1771 .gop_markupdate = udf_gop_markupdate, 1772 }; 1773 1774 /* --------------------------------------------------------------------- */ 1775 1776 /* 1777 * Each node can have an attached streamdir node though not 1778 * recursively. These are otherwise known as named substreams/named 1779 * extended attributes that have no size limitations. 1780 * 1781 * `Normal' extended attributes are indicated with a number and are recorded 1782 * in either the fe/efe descriptor itself for small descriptors or recorded in 1783 * the attached extended attribute file. Since this file can get fragmented, 1784 * care ought to be taken. 1785 */ 1786 1787 int 1788 udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, 1789 struct udf_node **noderes) 1790 { 1791 union dscrptr *dscr, *tmpdscr; 1792 struct udf_node *node; 1793 struct vnode *nvp; 1794 struct long_ad icb_loc; 1795 extern int (**udf_vnodeop_p)(void *); 1796 uint64_t file_size; 1797 uint32_t lb_size, sector, dummy; 1798 int udf_file_type, dscr_type, strat, strat4096, needs_indirect; 1799 int error; 1800 1801 DPRINTF(NODE, ("udf_get_node called\n")); 1802 *noderes = node = NULL; 1803 1804 /* lock to disallow simultanious creation of same node */ 1805 lockmgr(&ump->get_node_lock, LK_EXCLUSIVE, NULL); 1806 1807 DPRINTF(NODE, ("\tlookup in hash table\n")); 1808 /* lookup in hash table */ 1809 assert(ump); 1810 assert(node_icb_loc); 1811 node = udf_hashget(ump, node_icb_loc); 1812 if (node) { 1813 DPRINTF(NODE, ("\tgot it from the hash!\n")); 1814 /* vnode is returned locked */ 1815 *noderes = node; 1816 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1817 return 0; 1818 } 1819 1820 /* garbage check: translate node_icb_loc to sectornr */ 1821 error = udf_translate_vtop(ump, node_icb_loc, §or, &dummy); 1822 if (error) { 1823 /* no use, this will fail anyway */ 1824 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1825 return EINVAL; 1826 } 1827 1828 /* build node (do initialise!) */ 1829 node = pool_get(&udf_node_pool, PR_WAITOK); 1830 memset(node, 0, sizeof(struct udf_node)); 1831 1832 DPRINTF(NODE, ("\tget new vnode\n")); 1833 /* give it a vnode */ 1834 error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, &nvp); 1835 if (error) { 1836 pool_put(&udf_node_pool, node); 1837 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1838 return error; 1839 } 1840 1841 /* allways return locked vnode */ 1842 if ((error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY))) { 1843 /* recycle vnode and unlock; simultanious will fail too */ 1844 ungetnewvnode(nvp); 1845 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1846 return error; 1847 } 1848 1849 /* initialise crosslinks, note location of fe/efe for hashing */ 1850 node->ump = ump; 1851 node->vnode = nvp; 1852 nvp->v_data = node; 1853 node->loc = *node_icb_loc; 1854 node->lockf = 0; 1855 1856 /* insert into the hash lookup */ 1857 udf_hashins(node); 1858 1859 /* safe to unlock, the entry is in the hash table, vnode is locked */ 1860 lockmgr(&ump->get_node_lock, LK_RELEASE, NULL); 1861 1862 icb_loc = *node_icb_loc; 1863 needs_indirect = 0; 1864 strat4096 = 0; 1865 udf_file_type = UDF_ICB_FILETYPE_UNKNOWN; 1866 file_size = 0; 1867 lb_size = udf_rw32(ump->logical_vol->lb_size); 1868 1869 do { 1870 error = udf_translate_vtop(ump, &icb_loc, §or, &dummy); 1871 if (error) 1872 break; 1873 1874 /* try to read in fe/efe */ 1875 error = udf_read_descriptor(ump, sector, M_UDFTEMP, &tmpdscr); 1876 1877 /* blank sector marks end of sequence, check this */ 1878 if ((tmpdscr == NULL) && (!strat4096)) 1879 error = ENOENT; 1880 1881 /* break if read error or blank sector */ 1882 if (error || (tmpdscr == NULL)) 1883 break; 1884 1885 /* process descriptor based on the descriptor type */ 1886 dscr_type = udf_rw16(tmpdscr->tag.id); 1887 1888 /* if dealing with an indirect entry, follow the link */ 1889 if (dscr_type == TAGID_INDIRECT_ENTRY) { 1890 needs_indirect = 0; 1891 icb_loc = tmpdscr->inde.indirect_icb; 1892 free(tmpdscr, M_UDFTEMP); 1893 continue; 1894 } 1895 1896 /* only file entries and extended file entries allowed here */ 1897 if ((dscr_type != TAGID_FENTRY) && 1898 (dscr_type != TAGID_EXTFENTRY)) { 1899 free(tmpdscr, M_UDFTEMP); 1900 error = ENOENT; 1901 break; 1902 } 1903 1904 /* get descriptor space from our pool */ 1905 KASSERT(udf_tagsize(tmpdscr, lb_size) == lb_size); 1906 1907 dscr = pool_get(ump->desc_pool, PR_WAITOK); 1908 memcpy(dscr, tmpdscr, lb_size); 1909 free(tmpdscr, M_UDFTEMP); 1910 1911 /* record and process/update (ext)fentry */ 1912 if (dscr_type == TAGID_FENTRY) { 1913 if (node->fe) 1914 pool_put(ump->desc_pool, node->fe); 1915 node->fe = &dscr->fe; 1916 strat = udf_rw16(node->fe->icbtag.strat_type); 1917 udf_file_type = node->fe->icbtag.file_type; 1918 file_size = udf_rw64(node->fe->inf_len); 1919 } else { 1920 if (node->efe) 1921 pool_put(ump->desc_pool, node->efe); 1922 node->efe = &dscr->efe; 1923 strat = udf_rw16(node->efe->icbtag.strat_type); 1924 udf_file_type = node->efe->icbtag.file_type; 1925 file_size = udf_rw64(node->efe->inf_len); 1926 } 1927 1928 /* check recording strategy (structure) */ 1929 1930 /* 1931 * Strategy 4096 is a daisy linked chain terminating with an 1932 * unrecorded sector or a TERM descriptor. The next 1933 * descriptor is to be found in the sector that follows the 1934 * current sector. 1935 */ 1936 if (strat == 4096) { 1937 strat4096 = 1; 1938 needs_indirect = 1; 1939 1940 icb_loc.loc.lb_num = udf_rw32(icb_loc.loc.lb_num) + 1; 1941 } 1942 1943 /* 1944 * Strategy 4 is the normal strategy and terminates, but if 1945 * we're in strategy 4096, we can't have strategy 4 mixed in 1946 */ 1947 1948 if (strat == 4) { 1949 if (strat4096) { 1950 error = EINVAL; 1951 break; 1952 } 1953 break; /* done */ 1954 } 1955 } while (!error); 1956 1957 if (error) { 1958 /* recycle udf_node */ 1959 udf_dispose_node(node); 1960 1961 /* recycle vnode */ 1962 nvp->v_data = NULL; 1963 ungetnewvnode(nvp); 1964 1965 return EINVAL; /* error code ok? */ 1966 } 1967 1968 /* post process and initialise node */ 1969 1970 /* assert no references to dscr anymore beyong this point */ 1971 assert((node->fe) || (node->efe)); 1972 dscr = NULL; 1973 1974 /* 1975 * Record where to record an updated version of the descriptor. If 1976 * there is a sequence of indirect entries, icb_loc will have been 1977 * updated. Its the write disipline to allocate new space and to make 1978 * sure the chain is maintained. 1979 * 1980 * `needs_indirect' flags if the next location is to be filled with 1981 * with an indirect entry. 1982 */ 1983 node->next_loc = icb_loc; 1984 node->needs_indirect = needs_indirect; 1985 1986 /* 1987 * Translate UDF filetypes into vnode types. 1988 * 1989 * Systemfiles like the meta main and mirror files are not treated as 1990 * normal files, so we type them as having no type. UDF dictates that 1991 * they are not allowed to be visible. 1992 */ 1993 1994 /* TODO specfs, fifofs etc etc. vnops setting */ 1995 switch (udf_file_type) { 1996 case UDF_ICB_FILETYPE_DIRECTORY : 1997 case UDF_ICB_FILETYPE_STREAMDIR : 1998 nvp->v_type = VDIR; 1999 break; 2000 case UDF_ICB_FILETYPE_BLOCKDEVICE : 2001 nvp->v_type = VBLK; 2002 break; 2003 case UDF_ICB_FILETYPE_CHARDEVICE : 2004 nvp->v_type = VCHR; 2005 break; 2006 case UDF_ICB_FILETYPE_SYMLINK : 2007 nvp->v_type = VLNK; 2008 break; 2009 case UDF_ICB_FILETYPE_META_MAIN : 2010 case UDF_ICB_FILETYPE_META_MIRROR : 2011 nvp->v_type = VNON; 2012 break; 2013 case UDF_ICB_FILETYPE_RANDOMACCESS : 2014 nvp->v_type = VREG; 2015 break; 2016 default: 2017 /* YIKES, either a block/char device, fifo or something else */ 2018 nvp->v_type = VNON; 2019 } 2020 2021 /* initialise genfs */ 2022 genfs_node_init(nvp, &udf_genfsops); 2023 2024 /* don't forget to set vnode's v_size */ 2025 nvp->v_size = file_size; 2026 2027 /* TODO ext attr and streamdir nodes */ 2028 2029 *noderes = node; 2030 2031 return 0; 2032 } 2033 2034 /* --------------------------------------------------------------------- */ 2035 2036 /* UDF<->unix converters */ 2037 2038 /* --------------------------------------------------------------------- */ 2039 2040 static mode_t 2041 udf_perm_to_unix_mode(uint32_t perm) 2042 { 2043 mode_t mode; 2044 2045 mode = ((perm & UDF_FENTRY_PERM_USER_MASK) ); 2046 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK ) >> 2); 2047 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 2048 2049 return mode; 2050 } 2051 2052 /* --------------------------------------------------------------------- */ 2053 2054 #ifdef notyet 2055 static uint32_t 2056 unix_mode_to_udf_perm(mode_t mode) 2057 { 2058 uint32_t perm; 2059 2060 perm = ((mode & S_IRWXO) ); 2061 perm |= ((mode & S_IRWXG) << 2); 2062 perm |= ((mode & S_IRWXU) << 4); 2063 perm |= ((mode & S_IWOTH) << 3); 2064 perm |= ((mode & S_IWGRP) << 5); 2065 perm |= ((mode & S_IWUSR) << 7); 2066 2067 return perm; 2068 } 2069 #endif 2070 2071 /* --------------------------------------------------------------------- */ 2072 2073 static uint32_t 2074 udf_icb_to_unix_filetype(uint32_t icbftype) 2075 { 2076 switch (icbftype) { 2077 case UDF_ICB_FILETYPE_DIRECTORY : 2078 case UDF_ICB_FILETYPE_STREAMDIR : 2079 return S_IFDIR; 2080 case UDF_ICB_FILETYPE_FIFO : 2081 return S_IFIFO; 2082 case UDF_ICB_FILETYPE_CHARDEVICE : 2083 return S_IFCHR; 2084 case UDF_ICB_FILETYPE_BLOCKDEVICE : 2085 return S_IFBLK; 2086 case UDF_ICB_FILETYPE_RANDOMACCESS : 2087 return S_IFREG; 2088 case UDF_ICB_FILETYPE_SYMLINK : 2089 return S_IFLNK; 2090 case UDF_ICB_FILETYPE_SOCKET : 2091 return S_IFSOCK; 2092 } 2093 /* no idea what this is */ 2094 return 0; 2095 } 2096 2097 /* --------------------------------------------------------------------- */ 2098 2099 /* TODO KNF-ify */ 2100 2101 void 2102 udf_to_unix_name(char *result, char *id, int len, struct charspec *chsp) 2103 { 2104 uint16_t *raw_name, *unix_name; 2105 uint16_t *inchp, ch; 2106 uint8_t *outchp; 2107 int ucode_chars, nice_uchars; 2108 2109 raw_name = malloc(2048 * sizeof(uint16_t), M_UDFTEMP, M_WAITOK); 2110 unix_name = raw_name + 1024; /* split space in half */ 2111 assert(sizeof(char) == sizeof(uint8_t)); 2112 outchp = (uint8_t *) result; 2113 if ((chsp->type == 0) && (strcmp((char*) chsp->inf, "OSTA Compressed Unicode") == 0)) { 2114 *raw_name = *unix_name = 0; 2115 ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name); 2116 ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name)); 2117 nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars); 2118 for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) { 2119 ch = *inchp; 2120 /* XXX sloppy unicode -> latin */ 2121 *outchp++ = ch & 255; 2122 if (!ch) break; 2123 } 2124 *outchp++ = 0; 2125 } else { 2126 /* assume 8bit char length byte latin-1 */ 2127 assert(*id == 8); 2128 strncpy((char *) result, (char *) (id+1), strlen((char *) (id+1))); 2129 } 2130 free(raw_name, M_UDFTEMP); 2131 } 2132 2133 /* --------------------------------------------------------------------- */ 2134 2135 /* TODO KNF-ify */ 2136 2137 void 2138 unix_to_udf_name(char *result, char *name, 2139 uint8_t *result_len, struct charspec *chsp) 2140 { 2141 uint16_t *raw_name; 2142 int udf_chars, name_len; 2143 char *inchp; 2144 uint16_t *outchp; 2145 2146 raw_name = malloc(1024, M_UDFTEMP, M_WAITOK); 2147 /* convert latin-1 or whatever to unicode-16 */ 2148 *raw_name = 0; 2149 name_len = 0; 2150 inchp = name; 2151 outchp = raw_name; 2152 while (*inchp) { 2153 *outchp++ = (uint16_t) (*inchp++); 2154 name_len++; 2155 } 2156 2157 if ((chsp->type == 0) && (strcmp((char *) chsp->inf, "OSTA Compressed Unicode") == 0)) { 2158 udf_chars = udf_CompressUnicode(name_len, 8, (unicode_t *) raw_name, (byte *) result); 2159 } else { 2160 /* XXX assume 8bit char length byte latin-1 */ 2161 *result++ = 8; udf_chars = 1; 2162 strncpy(result, name + 1, strlen(name+1)); 2163 udf_chars += strlen(name); 2164 } 2165 *result_len = udf_chars; 2166 free(raw_name, M_UDFTEMP); 2167 } 2168 2169 /* --------------------------------------------------------------------- */ 2170 2171 /* 2172 * Timestamp to timespec conversion code is taken with small modifications 2173 * from FreeBSDs /sys/fs/udf by Scott Long <scottl@freebsd.org>. Added with 2174 * permission from Scott. 2175 */ 2176 2177 static int mon_lens[2][12] = { 2178 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 2179 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 2180 }; 2181 2182 2183 static int 2184 udf_isaleapyear(int year) 2185 { 2186 int i; 2187 2188 i = (year % 4) ? 0 : 1; 2189 i &= (year % 100) ? 1 : 0; 2190 i |= (year % 400) ? 0 : 1; 2191 2192 return i; 2193 } 2194 2195 2196 void 2197 udf_timestamp_to_timespec(struct udf_mount *ump, 2198 struct timestamp *timestamp, 2199 struct timespec *timespec) 2200 { 2201 uint32_t usecs, secs, nsecs; 2202 uint16_t tz; 2203 int i, lpyear, daysinyear, year; 2204 2205 timespec->tv_sec = secs = 0; 2206 timespec->tv_nsec = nsecs = 0; 2207 2208 /* 2209 * DirectCD seems to like using bogus year values. 2210 * 2211 * Distrust time->month especially, since it will be used for an array 2212 * index. 2213 */ 2214 year = udf_rw16(timestamp->year); 2215 if ((year < 1970) || (timestamp->month > 12)) { 2216 return; 2217 } 2218 2219 /* Calculate the time and day 2220 * Day is 1-31, Month is 1-12 2221 */ 2222 2223 usecs = timestamp->usec + 2224 100*timestamp->hund_usec + 10000*timestamp->centisec; 2225 nsecs = usecs * 1000; 2226 secs = timestamp->second; 2227 secs += timestamp->minute * 60; 2228 secs += timestamp->hour * 3600; 2229 secs += (timestamp->day-1) * 3600 * 24; 2230 2231 /* Calclulate the month */ 2232 lpyear = udf_isaleapyear(year); 2233 for (i = 1; i < timestamp->month; i++) 2234 secs += mon_lens[lpyear][i-1] * 3600 * 24; 2235 2236 for (i = 1970; i < year; i++) { 2237 daysinyear = udf_isaleapyear(i) + 365 ; 2238 secs += daysinyear * 3600 * 24; 2239 } 2240 2241 /* 2242 * Calculate the time zone. The timezone is 12 bit signed 2's 2243 * compliment, so we gotta do some extra magic to handle it right. 2244 */ 2245 tz = udf_rw16(timestamp->type_tz); 2246 tz &= 0x0fff; /* only lower 12 bits are significant */ 2247 if (tz & 0x0800) /* sign extention */ 2248 tz |= 0xf000; 2249 2250 /* TODO check timezone conversion */ 2251 /* check if we are specified a timezone to convert */ 2252 if (udf_rw16(timestamp->type_tz) & 0x1000) { 2253 if ((int16_t) tz != -2047) 2254 secs -= (int16_t) tz * 60; 2255 } else { 2256 secs -= ump->mount_args.gmtoff; 2257 } 2258 2259 timespec->tv_sec = secs; 2260 timespec->tv_nsec = nsecs; 2261 } 2262 2263 /* --------------------------------------------------------------------- */ 2264 2265 /* 2266 * Attribute and filetypes converters with get/set pairs 2267 */ 2268 2269 uint32_t 2270 udf_getaccessmode(struct udf_node *udf_node) 2271 { 2272 struct file_entry *fe; 2273 struct extfile_entry *efe; 2274 uint32_t udf_perm, icbftype; 2275 uint32_t mode, ftype; 2276 uint16_t icbflags; 2277 2278 if (udf_node->fe) { 2279 fe = udf_node->fe; 2280 udf_perm = udf_rw32(fe->perm); 2281 icbftype = fe->icbtag.file_type; 2282 icbflags = udf_rw16(fe->icbtag.flags); 2283 } else { 2284 assert(udf_node->efe); 2285 efe = udf_node->efe; 2286 udf_perm = udf_rw32(efe->perm); 2287 icbftype = efe->icbtag.file_type; 2288 icbflags = udf_rw16(efe->icbtag.flags); 2289 } 2290 2291 mode = udf_perm_to_unix_mode(udf_perm); 2292 ftype = udf_icb_to_unix_filetype(icbftype); 2293 2294 /* set suid, sgid, sticky from flags in fe/efe */ 2295 if (icbflags & UDF_ICB_TAG_FLAGS_SETUID) 2296 mode |= S_ISUID; 2297 if (icbflags & UDF_ICB_TAG_FLAGS_SETGID) 2298 mode |= S_ISGID; 2299 if (icbflags & UDF_ICB_TAG_FLAGS_STICKY) 2300 mode |= S_ISVTX; 2301 2302 return mode | ftype; 2303 } 2304 2305 /* --------------------------------------------------------------------- */ 2306 2307 /* 2308 * Directory read and manipulation functions 2309 */ 2310 2311 int 2312 udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, 2313 struct long_ad *icb_loc) 2314 { 2315 struct udf_node *dir_node = VTOI(vp); 2316 struct file_entry *fe; 2317 struct extfile_entry *efe; 2318 struct fileid_desc *fid; 2319 struct dirent dirent; 2320 uint64_t file_size, diroffset; 2321 uint32_t lb_size; 2322 int found, error; 2323 2324 /* get directory filesize */ 2325 if (dir_node->fe) { 2326 fe = dir_node->fe; 2327 file_size = udf_rw64(fe->inf_len); 2328 } else { 2329 assert(dir_node->efe); 2330 efe = dir_node->efe; 2331 file_size = udf_rw64(efe->inf_len); 2332 } 2333 2334 /* allocate temporary space for fid */ 2335 lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 2336 fid = malloc(lb_size, M_TEMP, M_WAITOK); 2337 2338 found = 0; 2339 diroffset = dir_node->last_diroffset; 2340 while (!found) { 2341 /* if not found in this track, turn trough zero */ 2342 if (diroffset >= file_size) 2343 diroffset = 0; 2344 2345 /* transfer a new fid/dirent */ 2346 error = udf_read_fid_stream(vp, &diroffset, fid, &dirent); 2347 if (error) 2348 break; 2349 2350 /* skip deleted entries */ 2351 if ((fid->file_char & UDF_FILE_CHAR_DEL) == 0) { 2352 if ((strlen(dirent.d_name) == namelen) && 2353 (strncmp(dirent.d_name, name, namelen) == 0)) { 2354 found = 1; 2355 *icb_loc = fid->icb; 2356 } 2357 } 2358 2359 if (diroffset == dir_node->last_diroffset) { 2360 /* we have cycled */ 2361 break; 2362 } 2363 } 2364 free(fid, M_TEMP); 2365 dir_node->last_diroffset = diroffset; 2366 2367 return found; 2368 } 2369 2370 /* --------------------------------------------------------------------- */ 2371 2372 /* 2373 * Read one fid and process it into a dirent and advance to the next (*fid) 2374 * has to be allocated a logical block in size, (*dirent) struct dirent length 2375 */ 2376 2377 int 2378 udf_read_fid_stream(struct vnode *vp, uint64_t *offset, 2379 struct fileid_desc *fid, struct dirent *dirent) 2380 { 2381 struct udf_node *dir_node = VTOI(vp); 2382 struct udf_mount *ump = dir_node->ump; 2383 struct file_entry *fe; 2384 struct extfile_entry *efe; 2385 struct uio dir_uio; 2386 struct iovec dir_iovec; 2387 uint32_t entry_length, lb_size; 2388 uint64_t file_size; 2389 char *fid_name; 2390 int enough, error; 2391 2392 assert(fid); 2393 assert(dirent); 2394 assert(dir_node); 2395 assert(offset); 2396 assert(*offset != 1); 2397 2398 DPRINTF(FIDS, ("read_fid_stream called\n")); 2399 /* check if we're past the end of the directory */ 2400 if (dir_node->fe) { 2401 fe = dir_node->fe; 2402 file_size = udf_rw64(fe->inf_len); 2403 } else { 2404 assert(dir_node->efe); 2405 efe = dir_node->efe; 2406 file_size = udf_rw64(efe->inf_len); 2407 } 2408 if (*offset >= file_size) 2409 return EINVAL; 2410 2411 /* get maximum length of FID descriptor */ 2412 lb_size = udf_rw32(ump->logical_vol->lb_size); 2413 2414 /* initialise return values */ 2415 entry_length = 0; 2416 memset(dirent, 0, sizeof(struct dirent)); 2417 memset(fid, 0, lb_size); 2418 2419 /* TODO use vn_rdwr instead of creating our own uio */ 2420 /* read part of the directory */ 2421 memset(&dir_uio, 0, sizeof(struct uio)); 2422 dir_uio.uio_rw = UIO_READ; /* read into this space */ 2423 dir_uio.uio_iovcnt = 1; 2424 dir_uio.uio_iov = &dir_iovec; 2425 UIO_SETUP_SYSSPACE(&dir_uio); 2426 dir_iovec.iov_base = fid; 2427 dir_iovec.iov_len = lb_size; 2428 dir_uio.uio_offset = *offset; 2429 2430 /* limit length of read in piece */ 2431 dir_uio.uio_resid = MIN(file_size - (*offset), lb_size); 2432 2433 /* read the part into the fid space */ 2434 error = VOP_READ(vp, &dir_uio, IO_ALTSEMANTICS, NOCRED); 2435 if (error) 2436 return error; 2437 2438 /* 2439 * Check if we got a whole descriptor. 2440 * XXX Try to `resync' directory stream when something is very wrong. 2441 * 2442 */ 2443 enough = (dir_uio.uio_offset - (*offset) >= UDF_FID_SIZE); 2444 if (!enough) { 2445 /* short dir ... */ 2446 return EIO; 2447 } 2448 2449 /* check if our FID header is OK */ 2450 error = udf_check_tag(fid); 2451 DPRINTFIF(FIDS, error, ("read fids: tag check failed\n")); 2452 if (!error) { 2453 if (udf_rw16(fid->tag.id) != TAGID_FID) 2454 error = ENOENT; 2455 } 2456 DPRINTFIF(FIDS, !error, ("\ttag checked ok: got TAGID_FID\n")); 2457 2458 /* check for length */ 2459 if (!error) { 2460 entry_length = udf_fidsize(fid, lb_size); 2461 enough = (dir_uio.uio_offset - (*offset) >= entry_length); 2462 } 2463 DPRINTFIF(FIDS, !error, ("\tentry_length = %d, enough = %s\n", 2464 entry_length, enough?"yes":"no")); 2465 2466 if (!enough) { 2467 /* short dir ... bomb out */ 2468 return EIO; 2469 } 2470 2471 /* check FID contents */ 2472 if (!error) { 2473 error = udf_check_tag_payload((union dscrptr *) fid, lb_size); 2474 DPRINTF(FIDS, ("\tpayload checked ok\n")); 2475 } 2476 if (error) { 2477 /* note that is sometimes a bit quick to report */ 2478 printf("BROKEN DIRECTORY ENTRY\n"); 2479 /* RESYNC? */ 2480 /* TODO: use udf_resync_fid_stream */ 2481 return EIO; 2482 } 2483 DPRINTF(FIDS, ("\tinterpret FID\n")); 2484 2485 /* we got a whole and valid descriptor! */ 2486 2487 /* create resulting dirent structure */ 2488 fid_name = (char *) fid->data + udf_rw16(fid->l_iu); 2489 udf_to_unix_name(dirent->d_name, 2490 fid_name, fid->l_fi, &ump->logical_vol->desc_charset); 2491 2492 /* '..' has no name, so provide one */ 2493 if (fid->file_char & UDF_FILE_CHAR_PAR) 2494 strcpy(dirent->d_name, ".."); 2495 2496 dirent->d_fileno = udf_calchash(&fid->icb); /* inode hash XXX */ 2497 dirent->d_namlen = strlen(dirent->d_name); 2498 dirent->d_reclen = _DIRENT_SIZE(dirent); 2499 2500 /* 2501 * Note that its not worth trying to go for the filetypes now... its 2502 * too expensive too 2503 */ 2504 dirent->d_type = DT_UNKNOWN; 2505 2506 /* initial guess for filetype we can make */ 2507 if (fid->file_char & UDF_FILE_CHAR_DIR) 2508 dirent->d_type = DT_DIR; 2509 2510 /* advance */ 2511 *offset += entry_length; 2512 2513 return error; 2514 } 2515 2516 /* --------------------------------------------------------------------- */ 2517 2518 /* 2519 * block based file reading and writing 2520 */ 2521 2522 static int 2523 udf_read_internal(struct udf_node *node, uint8_t *blob) 2524 { 2525 struct udf_mount *ump; 2526 struct file_entry *fe; 2527 struct extfile_entry *efe; 2528 uint64_t inflen; 2529 uint32_t sector_size; 2530 uint8_t *pos; 2531 int icbflags, addr_type; 2532 2533 /* shut up gcc */ 2534 inflen = addr_type = icbflags = 0; 2535 pos = NULL; 2536 2537 /* get extent and do some paranoia checks */ 2538 ump = node->ump; 2539 sector_size = ump->discinfo.sector_size; 2540 2541 fe = node->fe; 2542 efe = node->efe; 2543 if (fe) { 2544 inflen = udf_rw64(fe->inf_len); 2545 pos = &fe->data[0] + udf_rw32(fe->l_ea); 2546 icbflags = udf_rw16(fe->icbtag.flags); 2547 } 2548 if (efe) { 2549 inflen = udf_rw64(efe->inf_len); 2550 pos = &efe->data[0] + udf_rw32(efe->l_ea); 2551 icbflags = udf_rw16(efe->icbtag.flags); 2552 } 2553 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2554 2555 assert(addr_type == UDF_ICB_INTERN_ALLOC); 2556 assert(inflen < sector_size); 2557 2558 /* copy out info */ 2559 memset(blob, 0, sector_size); 2560 memcpy(blob, pos, inflen); 2561 2562 return 0; 2563 } 2564 2565 /* --------------------------------------------------------------------- */ 2566 2567 /* 2568 * Read file extent reads an extent specified in sectors from the file. It is 2569 * sector based; i.e. no `fancy' offsets. 2570 */ 2571 2572 int 2573 udf_read_file_extent(struct udf_node *node, 2574 uint32_t from, uint32_t sectors, 2575 uint8_t *blob) 2576 { 2577 struct buf buf; 2578 uint32_t sector_size; 2579 2580 BUF_INIT(&buf); 2581 2582 sector_size = node->ump->discinfo.sector_size; 2583 2584 buf.b_bufsize = sectors * sector_size; 2585 buf.b_data = blob; 2586 buf.b_bcount = buf.b_bufsize; 2587 buf.b_resid = buf.b_bcount; 2588 buf.b_flags = B_BUSY | B_READ; 2589 buf.b_vp = node->vnode; 2590 buf.b_proc = NULL; 2591 2592 buf.b_blkno = from; 2593 buf.b_lblkno = 0; 2594 BIO_SETPRIO(&buf, BPRIO_TIMELIMITED); 2595 2596 udf_read_filebuf(node, &buf); 2597 return biowait(&buf); 2598 } 2599 2600 2601 /* --------------------------------------------------------------------- */ 2602 2603 /* 2604 * Read file extent in the buffer. 2605 * 2606 * The splitup of the extent into seperate request-buffers is to minimise 2607 * copying around as much as possible. 2608 */ 2609 2610 2611 /* maximum of 128 translations (!) (64 kb in 512 byte sectors) */ 2612 #define FILEBUFSECT 128 2613 2614 void 2615 udf_read_filebuf(struct udf_node *node, struct buf *buf) 2616 { 2617 struct buf *nestbuf; 2618 uint64_t *mapping; 2619 uint64_t run_start; 2620 uint32_t sector_size; 2621 uint32_t buf_offset, sector, rbuflen, rblk; 2622 uint8_t *buf_pos; 2623 int error, run_length; 2624 2625 uint32_t from; 2626 uint32_t sectors; 2627 2628 sector_size = node->ump->discinfo.sector_size; 2629 2630 from = buf->b_blkno; 2631 sectors = buf->b_bcount / sector_size; 2632 2633 /* assure we have enough translation slots */ 2634 KASSERT(buf->b_bcount / sector_size <= FILEBUFSECT); 2635 KASSERT(MAXPHYS / sector_size <= FILEBUFSECT); 2636 2637 if (sectors > FILEBUFSECT) { 2638 printf("udf_read_filebuf: implementation limit on bufsize\n"); 2639 buf->b_error = EIO; 2640 buf->b_flags |= B_ERROR; 2641 biodone(buf); 2642 return; 2643 } 2644 2645 mapping = malloc(sizeof(*mapping) * FILEBUFSECT, M_TEMP, M_WAITOK); 2646 2647 error = 0; 2648 DPRINTF(READ, ("\ttranslate %d-%d\n", from, sectors)); 2649 error = udf_translate_file_extent(node, from, sectors, mapping); 2650 if (error) { 2651 buf->b_error = error; 2652 buf->b_flags |= B_ERROR; 2653 biodone(buf); 2654 goto out; 2655 } 2656 DPRINTF(READ, ("\ttranslate extent went OK\n")); 2657 2658 /* pre-check if internal or parts are zero */ 2659 if (*mapping == UDF_TRANS_INTERN) { 2660 error = udf_read_internal(node, (uint8_t *) buf->b_data); 2661 if (error) { 2662 buf->b_error = error; 2663 buf->b_flags |= B_ERROR; 2664 } 2665 biodone(buf); 2666 goto out; 2667 } 2668 DPRINTF(READ, ("\tnot intern\n")); 2669 2670 /* request read-in of data from disc sheduler */ 2671 buf->b_resid = buf->b_bcount; 2672 for (sector = 0; sector < sectors; sector++) { 2673 buf_offset = sector * sector_size; 2674 buf_pos = (uint8_t *) buf->b_data + buf_offset; 2675 DPRINTF(READ, ("\tprocessing rel sector %d\n", sector)); 2676 2677 switch (mapping[sector]) { 2678 case UDF_TRANS_UNMAPPED: 2679 case UDF_TRANS_ZERO: 2680 /* copy zero sector */ 2681 memset(buf_pos, 0, sector_size); 2682 DPRINTF(READ, ("\treturning zero sector\n")); 2683 nestiobuf_done(buf, sector_size, 0); 2684 break; 2685 default : 2686 DPRINTF(READ, ("\tread sector " 2687 "%"PRIu64"\n", mapping[sector])); 2688 2689 run_start = mapping[sector]; 2690 run_length = 1; 2691 while (sector < sectors-1) { 2692 if (mapping[sector+1] != mapping[sector]+1) 2693 break; 2694 run_length++; 2695 sector++; 2696 } 2697 2698 /* 2699 * nest an iobuf and mark it for async reading. Since 2700 * we're using nested buffers, they can't be cached by 2701 * design. 2702 */ 2703 rbuflen = run_length * sector_size; 2704 rblk = run_start * (sector_size/DEV_BSIZE); 2705 2706 nestbuf = getiobuf(); 2707 nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen); 2708 /* nestbuf is B_ASYNC */ 2709 2710 /* CD shedules on raw blkno */ 2711 nestbuf->b_blkno = rblk; 2712 nestbuf->b_proc = NULL; 2713 nestbuf->b_cylinder = 0; 2714 nestbuf->b_rawblkno = rblk; 2715 VOP_STRATEGY(node->ump->devvp, nestbuf); 2716 } 2717 } 2718 out: 2719 DPRINTF(READ, ("\tend of read_filebuf\n")); 2720 free(mapping, M_TEMP); 2721 return; 2722 } 2723 #undef FILEBUFSECT 2724 2725 2726 /* --------------------------------------------------------------------- */ 2727 2728 /* 2729 * Translate an extent (in sectors) into sector numbers; used for read and 2730 * write operations. DOESNT't check extents. 2731 */ 2732 2733 int 2734 udf_translate_file_extent(struct udf_node *node, 2735 uint32_t from, uint32_t pages, 2736 uint64_t *map) 2737 { 2738 struct udf_mount *ump; 2739 struct file_entry *fe; 2740 struct extfile_entry *efe; 2741 struct short_ad *s_ad; 2742 struct long_ad *l_ad, t_ad; 2743 uint64_t transsec; 2744 uint32_t sector_size, transsec32; 2745 uint32_t overlap, translen; 2746 uint32_t vpart_num, lb_num, len, alloclen; 2747 uint8_t *pos; 2748 int error, flags, addr_type, icblen, icbflags; 2749 2750 if (!node) 2751 return ENOENT; 2752 2753 /* shut up gcc */ 2754 alloclen = addr_type = icbflags = 0; 2755 pos = NULL; 2756 2757 /* do the work */ 2758 ump = node->ump; 2759 sector_size = ump->discinfo.sector_size; 2760 fe = node->fe; 2761 efe = node->efe; 2762 if (fe) { 2763 alloclen = udf_rw32(fe->l_ad); 2764 pos = &fe->data[0] + udf_rw32(fe->l_ea); 2765 icbflags = udf_rw16(fe->icbtag.flags); 2766 } 2767 if (efe) { 2768 alloclen = udf_rw32(efe->l_ad); 2769 pos = &efe->data[0] + udf_rw32(efe->l_ea); 2770 icbflags = udf_rw16(efe->icbtag.flags); 2771 } 2772 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2773 2774 DPRINTF(TRANSLATE, ("udf trans: alloc_len = %d, addr_type %d, " 2775 "fe %p, efe %p\n", alloclen, addr_type, fe, efe)); 2776 2777 vpart_num = udf_rw16(node->loc.loc.part_num); 2778 lb_num = len = icblen = 0; /* shut up gcc */ 2779 while (pages && alloclen) { 2780 DPRINTF(TRANSLATE, ("\taddr_type %d\n", addr_type)); 2781 switch (addr_type) { 2782 case UDF_ICB_INTERN_ALLOC : 2783 /* TODO check extents? */ 2784 *map = UDF_TRANS_INTERN; 2785 return 0; 2786 case UDF_ICB_SHORT_ALLOC : 2787 icblen = sizeof(struct short_ad); 2788 s_ad = (struct short_ad *) pos; 2789 len = udf_rw32(s_ad->len); 2790 lb_num = udf_rw32(s_ad->lb_num); 2791 break; 2792 case UDF_ICB_LONG_ALLOC : 2793 icblen = sizeof(struct long_ad); 2794 l_ad = (struct long_ad *) pos; 2795 len = udf_rw32(l_ad->len); 2796 lb_num = udf_rw32(l_ad->loc.lb_num); 2797 vpart_num = udf_rw16(l_ad->loc.part_num); 2798 DPRINTFIF(TRANSLATE, 2799 (l_ad->impl.im_used.flags & 2800 UDF_ADIMP_FLAGS_EXTENT_ERASED), 2801 ("UDF: got an `extent erased' flag in long_ad\n")); 2802 break; 2803 default: 2804 /* can't be here */ 2805 return EINVAL; /* for sure */ 2806 } 2807 2808 /* process extent */ 2809 flags = UDF_EXT_FLAGS(len); 2810 len = UDF_EXT_LEN(len); 2811 2812 overlap = (len + sector_size -1) / sector_size; 2813 if (from) { 2814 if (from > overlap) { 2815 from -= overlap; 2816 overlap = 0; 2817 } else { 2818 lb_num += from; /* advance in extent */ 2819 overlap -= from; 2820 from = 0; 2821 } 2822 } 2823 2824 overlap = MIN(overlap, pages); 2825 while (overlap) { 2826 switch (flags) { 2827 case UDF_EXT_REDIRECT : 2828 /* no support for allocation extentions yet */ 2829 /* TODO support for allocation extention */ 2830 return ENOENT; 2831 case UDF_EXT_FREED : 2832 case UDF_EXT_FREE : 2833 transsec = UDF_TRANS_ZERO; 2834 translen = overlap; 2835 while (overlap && pages && translen) { 2836 *map++ = transsec; 2837 lb_num++; 2838 overlap--; pages--; translen--; 2839 } 2840 break; 2841 case UDF_EXT_ALLOCATED : 2842 t_ad.loc.lb_num = udf_rw32(lb_num); 2843 t_ad.loc.part_num = udf_rw16(vpart_num); 2844 error = udf_translate_vtop(ump, 2845 &t_ad, &transsec32, &translen); 2846 transsec = transsec32; 2847 if (error) 2848 return error; 2849 while (overlap && pages && translen) { 2850 *map++ = transsec; 2851 lb_num++; transsec++; 2852 overlap--; pages--; translen--; 2853 } 2854 break; 2855 } 2856 } 2857 pos += icblen; 2858 alloclen -= icblen; 2859 } 2860 return 0; 2861 } 2862 2863 /* --------------------------------------------------------------------- */ 2864 2865