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