1 /* $NetBSD: udf_subr.c,v 1.73 2008/09/27 13:05:34 reinoud Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2008 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 29 30 #include <sys/cdefs.h> 31 #ifndef lint 32 __KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.73 2008/09/27 13:05:34 reinoud Exp $"); 33 #endif /* not lint */ 34 35 36 #if defined(_KERNEL_OPT) 37 #include "opt_quota.h" 38 #include "opt_compat_netbsd.h" 39 #endif 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/sysctl.h> 44 #include <sys/namei.h> 45 #include <sys/proc.h> 46 #include <sys/kernel.h> 47 #include <sys/vnode.h> 48 #include <miscfs/genfs/genfs_node.h> 49 #include <sys/mount.h> 50 #include <sys/buf.h> 51 #include <sys/file.h> 52 #include <sys/device.h> 53 #include <sys/disklabel.h> 54 #include <sys/ioctl.h> 55 #include <sys/malloc.h> 56 #include <sys/dirent.h> 57 #include <sys/stat.h> 58 #include <sys/conf.h> 59 #include <sys/kauth.h> 60 #include <fs/unicode.h> 61 #include <dev/clock_subr.h> 62 63 #include <fs/udf/ecma167-udf.h> 64 #include <fs/udf/udf_mount.h> 65 #include <sys/dirhash.h> 66 67 #include "udf.h" 68 #include "udf_subr.h" 69 #include "udf_bswap.h" 70 71 72 #define VTOI(vnode) ((struct udf_node *) (vnode)->v_data) 73 74 #define UDF_SET_SYSTEMFILE(vp) \ 75 /* XXXAD Is the vnode locked? */ \ 76 (vp)->v_vflag |= VV_SYSTEM; \ 77 vref(vp); \ 78 vput(vp); \ 79 80 extern int syncer_maxdelay; /* maximum delay time */ 81 extern int (**udf_vnodeop_p)(void *); 82 83 /* --------------------------------------------------------------------- */ 84 85 //#ifdef DEBUG 86 #if 1 87 88 #if 0 89 static void 90 udf_dumpblob(boid *blob, uint32_t dlen) 91 { 92 int i, j; 93 94 printf("blob = %p\n", blob); 95 printf("dump of %d bytes\n", dlen); 96 97 for (i = 0; i < dlen; i+ = 16) { 98 printf("%04x ", i); 99 for (j = 0; j < 16; j++) { 100 if (i+j < dlen) { 101 printf("%02x ", blob[i+j]); 102 } else { 103 printf(" "); 104 } 105 } 106 for (j = 0; j < 16; j++) { 107 if (i+j < dlen) { 108 if (blob[i+j]>32 && blob[i+j]! = 127) { 109 printf("%c", blob[i+j]); 110 } else { 111 printf("."); 112 } 113 } 114 } 115 printf("\n"); 116 } 117 printf("\n"); 118 Debugger(); 119 } 120 #endif 121 122 static void 123 udf_dump_discinfo(struct udf_mount *ump) 124 { 125 char bits[128]; 126 struct mmc_discinfo *di = &ump->discinfo; 127 128 if ((udf_verbose & UDF_DEBUG_VOLUMES) == 0) 129 return; 130 131 printf("Device/media info :\n"); 132 printf("\tMMC profile 0x%02x\n", di->mmc_profile); 133 printf("\tderived class %d\n", di->mmc_class); 134 printf("\tsector size %d\n", di->sector_size); 135 printf("\tdisc state %d\n", di->disc_state); 136 printf("\tlast ses state %d\n", di->last_session_state); 137 printf("\tbg format state %d\n", di->bg_format_state); 138 printf("\tfrst track %d\n", di->first_track); 139 printf("\tfst on last ses %d\n", di->first_track_last_session); 140 printf("\tlst on last ses %d\n", di->last_track_last_session); 141 printf("\tlink block penalty %d\n", di->link_block_penalty); 142 bitmask_snprintf(di->disc_flags, MMC_DFLAGS_FLAGBITS, bits, 143 sizeof(bits)); 144 printf("\tdisc flags %s\n", bits); 145 printf("\tdisc id %x\n", di->disc_id); 146 printf("\tdisc barcode %"PRIx64"\n", di->disc_barcode); 147 148 printf("\tnum sessions %d\n", di->num_sessions); 149 printf("\tnum tracks %d\n", di->num_tracks); 150 151 bitmask_snprintf(di->mmc_cur, MMC_CAP_FLAGBITS, bits, sizeof(bits)); 152 printf("\tcapabilities cur %s\n", bits); 153 bitmask_snprintf(di->mmc_cap, MMC_CAP_FLAGBITS, bits, sizeof(bits)); 154 printf("\tcapabilities cap %s\n", bits); 155 } 156 #else 157 #define udf_dump_discinfo(a); 158 #endif 159 160 161 /* --------------------------------------------------------------------- */ 162 163 /* not called often */ 164 int 165 udf_update_discinfo(struct udf_mount *ump) 166 { 167 struct vnode *devvp = ump->devvp; 168 struct partinfo dpart; 169 struct mmc_discinfo *di; 170 int error; 171 172 DPRINTF(VOLUMES, ("read/update disc info\n")); 173 di = &ump->discinfo; 174 memset(di, 0, sizeof(struct mmc_discinfo)); 175 176 /* check if we're on a MMC capable device, i.e. CD/DVD */ 177 error = VOP_IOCTL(devvp, MMCGETDISCINFO, di, FKIOCTL, NOCRED); 178 if (error == 0) { 179 udf_dump_discinfo(ump); 180 return 0; 181 } 182 183 /* disc partition support */ 184 error = VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, NOCRED); 185 if (error) 186 return ENODEV; 187 188 /* set up a disc info profile for partitions */ 189 di->mmc_profile = 0x01; /* disc type */ 190 di->mmc_class = MMC_CLASS_DISC; 191 di->disc_state = MMC_STATE_CLOSED; 192 di->last_session_state = MMC_STATE_CLOSED; 193 di->bg_format_state = MMC_BGFSTATE_COMPLETED; 194 di->link_block_penalty = 0; 195 196 di->mmc_cur = MMC_CAP_RECORDABLE | MMC_CAP_REWRITABLE | 197 MMC_CAP_ZEROLINKBLK | MMC_CAP_HW_DEFECTFREE; 198 di->mmc_cap = di->mmc_cur; 199 di->disc_flags = MMC_DFLAGS_UNRESTRICTED; 200 201 /* TODO problem with last_possible_lba on resizable VND; request */ 202 di->last_possible_lba = dpart.part->p_size; 203 di->sector_size = dpart.disklab->d_secsize; 204 205 di->num_sessions = 1; 206 di->num_tracks = 1; 207 208 di->first_track = 1; 209 di->first_track_last_session = di->last_track_last_session = 1; 210 211 udf_dump_discinfo(ump); 212 return 0; 213 } 214 215 216 int 217 udf_update_trackinfo(struct udf_mount *ump, struct mmc_trackinfo *ti) 218 { 219 struct vnode *devvp = ump->devvp; 220 struct mmc_discinfo *di = &ump->discinfo; 221 int error, class; 222 223 DPRINTF(VOLUMES, ("read track info\n")); 224 225 class = di->mmc_class; 226 if (class != MMC_CLASS_DISC) { 227 /* tracknr specified in struct ti */ 228 error = VOP_IOCTL(devvp, MMCGETTRACKINFO, ti, FKIOCTL, NOCRED); 229 return error; 230 } 231 232 /* disc partition support */ 233 if (ti->tracknr != 1) 234 return EIO; 235 236 /* create fake ti (TODO check for resized vnds) */ 237 ti->sessionnr = 1; 238 239 ti->track_mode = 0; /* XXX */ 240 ti->data_mode = 0; /* XXX */ 241 ti->flags = MMC_TRACKINFO_LRA_VALID | MMC_TRACKINFO_NWA_VALID; 242 243 ti->track_start = 0; 244 ti->packet_size = 1; 245 246 /* TODO support for resizable vnd */ 247 ti->track_size = di->last_possible_lba; 248 ti->next_writable = di->last_possible_lba; 249 ti->last_recorded = ti->next_writable; 250 ti->free_blocks = 0; 251 252 return 0; 253 } 254 255 256 int 257 udf_setup_writeparams(struct udf_mount *ump) 258 { 259 struct mmc_writeparams mmc_writeparams; 260 int error; 261 262 if (ump->discinfo.mmc_class == MMC_CLASS_DISC) 263 return 0; 264 265 /* 266 * only CD burning normally needs setting up, but other disc types 267 * might need other settings to be made. The MMC framework will set up 268 * the nessisary recording parameters according to the disc 269 * characteristics read in. Modifications can be made in the discinfo 270 * structure passed to change the nature of the disc. 271 */ 272 273 memset(&mmc_writeparams, 0, sizeof(struct mmc_writeparams)); 274 mmc_writeparams.mmc_class = ump->discinfo.mmc_class; 275 mmc_writeparams.mmc_cur = ump->discinfo.mmc_cur; 276 277 /* 278 * UDF dictates first track to determine track mode for the whole 279 * disc. [UDF 1.50/6.10.1.1, UDF 1.50/6.10.2.1] 280 * To prevent problems with a `reserved' track in front we start with 281 * the 2nd track and if that is not valid, go for the 1st. 282 */ 283 mmc_writeparams.tracknr = 2; 284 mmc_writeparams.data_mode = MMC_DATAMODE_DEFAULT; /* XA disc */ 285 mmc_writeparams.track_mode = MMC_TRACKMODE_DEFAULT; /* data */ 286 287 error = VOP_IOCTL(ump->devvp, MMCSETUPWRITEPARAMS, &mmc_writeparams, 288 FKIOCTL, NOCRED); 289 if (error) { 290 mmc_writeparams.tracknr = 1; 291 error = VOP_IOCTL(ump->devvp, MMCSETUPWRITEPARAMS, 292 &mmc_writeparams, FKIOCTL, NOCRED); 293 } 294 return error; 295 } 296 297 298 int 299 udf_synchronise_caches(struct udf_mount *ump) 300 { 301 struct mmc_op mmc_op; 302 303 DPRINTF(CALL, ("udf_synchronise_caches()\n")); 304 305 if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) 306 return 0; 307 308 /* discs are done now */ 309 if (ump->discinfo.mmc_class == MMC_CLASS_DISC) 310 return 0; 311 312 bzero(&mmc_op, sizeof(struct mmc_op)); 313 mmc_op.operation = MMC_OP_SYNCHRONISECACHE; 314 315 /* ignore return code */ 316 (void) VOP_IOCTL(ump->devvp, MMCOP, &mmc_op, FKIOCTL, NOCRED); 317 318 return 0; 319 } 320 321 /* --------------------------------------------------------------------- */ 322 323 /* track/session searching for mounting */ 324 int 325 udf_search_tracks(struct udf_mount *ump, struct udf_args *args, 326 int *first_tracknr, int *last_tracknr) 327 { 328 struct mmc_trackinfo trackinfo; 329 uint32_t tracknr, start_track, num_tracks; 330 int error; 331 332 /* if negative, sessionnr is relative to last session */ 333 if (args->sessionnr < 0) { 334 args->sessionnr += ump->discinfo.num_sessions; 335 } 336 337 /* sanity */ 338 if (args->sessionnr < 0) 339 args->sessionnr = 0; 340 if (args->sessionnr > ump->discinfo.num_sessions) 341 args->sessionnr = ump->discinfo.num_sessions; 342 343 /* search the tracks for this session, zero session nr indicates last */ 344 if (args->sessionnr == 0) 345 args->sessionnr = ump->discinfo.num_sessions; 346 if (ump->discinfo.last_session_state == MMC_STATE_EMPTY) 347 args->sessionnr--; 348 349 /* sanity again */ 350 if (args->sessionnr < 0) 351 args->sessionnr = 0; 352 353 /* search the first and last track of the specified session */ 354 num_tracks = ump->discinfo.num_tracks; 355 start_track = ump->discinfo.first_track; 356 357 /* search for first track of this session */ 358 for (tracknr = start_track; tracknr <= num_tracks; tracknr++) { 359 /* get track info */ 360 trackinfo.tracknr = tracknr; 361 error = udf_update_trackinfo(ump, &trackinfo); 362 if (error) 363 return error; 364 365 if (trackinfo.sessionnr == args->sessionnr) 366 break; 367 } 368 *first_tracknr = tracknr; 369 370 /* search for last track of this session */ 371 for (;tracknr <= num_tracks; tracknr++) { 372 /* get track info */ 373 trackinfo.tracknr = tracknr; 374 error = udf_update_trackinfo(ump, &trackinfo); 375 if (error || (trackinfo.sessionnr != args->sessionnr)) { 376 tracknr--; 377 break; 378 } 379 } 380 if (tracknr > num_tracks) 381 tracknr--; 382 383 *last_tracknr = tracknr; 384 385 if (*last_tracknr < *first_tracknr) { 386 printf( "udf_search_tracks: sanity check on drive+disc failed, " 387 "drive returned garbage\n"); 388 return EINVAL; 389 } 390 391 assert(*last_tracknr >= *first_tracknr); 392 return 0; 393 } 394 395 396 /* 397 * NOTE: this is the only routine in this file that directly peeks into the 398 * metadata file but since its at a larval state of the mount it can't hurt. 399 * 400 * XXX candidate for udf_allocation.c 401 * XXX clean me up!, change to new node reading code. 402 */ 403 404 static void 405 udf_check_track_metadata_overlap(struct udf_mount *ump, 406 struct mmc_trackinfo *trackinfo) 407 { 408 struct part_desc *part; 409 struct file_entry *fe; 410 struct extfile_entry *efe; 411 struct short_ad *s_ad; 412 struct long_ad *l_ad; 413 uint32_t track_start, track_end; 414 uint32_t phys_part_start, phys_part_end, part_start, part_end; 415 uint32_t sector_size, len, alloclen, plb_num; 416 uint8_t *pos; 417 int addr_type, icblen, icbflags, flags; 418 419 /* get our track extents */ 420 track_start = trackinfo->track_start; 421 track_end = track_start + trackinfo->track_size; 422 423 /* get our base partition extent */ 424 KASSERT(ump->node_part == ump->fids_part); 425 part = ump->partitions[ump->node_part]; 426 phys_part_start = udf_rw32(part->start_loc); 427 phys_part_end = phys_part_start + udf_rw32(part->part_len); 428 429 /* no use if its outside the physical partition */ 430 if ((phys_part_start >= track_end) || (phys_part_end < track_start)) 431 return; 432 433 /* 434 * now follow all extents in the fe/efe to see if they refer to this 435 * track 436 */ 437 438 sector_size = ump->discinfo.sector_size; 439 440 /* XXX should we claim exclusive access to the metafile ? */ 441 /* TODO: move to new node read code */ 442 fe = ump->metadata_node->fe; 443 efe = ump->metadata_node->efe; 444 if (fe) { 445 alloclen = udf_rw32(fe->l_ad); 446 pos = &fe->data[0] + udf_rw32(fe->l_ea); 447 icbflags = udf_rw16(fe->icbtag.flags); 448 } else { 449 assert(efe); 450 alloclen = udf_rw32(efe->l_ad); 451 pos = &efe->data[0] + udf_rw32(efe->l_ea); 452 icbflags = udf_rw16(efe->icbtag.flags); 453 } 454 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 455 456 while (alloclen) { 457 if (addr_type == UDF_ICB_SHORT_ALLOC) { 458 icblen = sizeof(struct short_ad); 459 s_ad = (struct short_ad *) pos; 460 len = udf_rw32(s_ad->len); 461 plb_num = udf_rw32(s_ad->lb_num); 462 } else { 463 /* should not be present, but why not */ 464 icblen = sizeof(struct long_ad); 465 l_ad = (struct long_ad *) pos; 466 len = udf_rw32(l_ad->len); 467 plb_num = udf_rw32(l_ad->loc.lb_num); 468 /* pvpart_num = udf_rw16(l_ad->loc.part_num); */ 469 } 470 /* process extent */ 471 flags = UDF_EXT_FLAGS(len); 472 len = UDF_EXT_LEN(len); 473 474 part_start = phys_part_start + plb_num; 475 part_end = part_start + (len / sector_size); 476 477 if ((part_start >= track_start) && (part_end <= track_end)) { 478 /* extent is enclosed within this track */ 479 ump->metadata_track = *trackinfo; 480 return; 481 } 482 483 pos += icblen; 484 alloclen -= icblen; 485 } 486 } 487 488 489 int 490 udf_search_writing_tracks(struct udf_mount *ump) 491 { 492 struct mmc_trackinfo trackinfo; 493 struct part_desc *part; 494 uint32_t tracknr, start_track, num_tracks; 495 uint32_t track_start, track_end, part_start, part_end; 496 int node_alloc, error; 497 498 /* 499 * in the CD/(HD)DVD/BD recordable device model a few tracks within 500 * the last session might be open but in the UDF device model at most 501 * three tracks can be open: a reserved track for delayed ISO VRS 502 * writing, a data track and a metadata track. We search here for the 503 * data track and the metadata track. Note that the reserved track is 504 * troublesome but can be detected by its small size of < 512 sectors. 505 */ 506 507 num_tracks = ump->discinfo.num_tracks; 508 start_track = ump->discinfo.first_track; 509 510 /* fetch info on first and possibly only track */ 511 trackinfo.tracknr = start_track; 512 error = udf_update_trackinfo(ump, &trackinfo); 513 if (error) 514 return error; 515 516 /* copy results to our mount point */ 517 ump->data_track = trackinfo; 518 ump->metadata_track = trackinfo; 519 520 /* if not sequential, we're done */ 521 if (num_tracks == 1) 522 return 0; 523 524 for (tracknr = start_track;tracknr <= num_tracks; tracknr++) { 525 /* get track info */ 526 trackinfo.tracknr = tracknr; 527 error = udf_update_trackinfo(ump, &trackinfo); 528 if (error) 529 return error; 530 531 if ((trackinfo.flags & MMC_TRACKINFO_NWA_VALID) == 0) 532 continue; 533 534 track_start = trackinfo.track_start; 535 track_end = track_start + trackinfo.track_size; 536 537 /* check for overlap on data partition */ 538 part = ump->partitions[ump->data_part]; 539 part_start = udf_rw32(part->start_loc); 540 part_end = part_start + udf_rw32(part->part_len); 541 if ((part_start < track_end) && (part_end > track_start)) { 542 ump->data_track = trackinfo; 543 /* TODO check if UDF partition data_part is writable */ 544 } 545 546 /* check for overlap on metadata partition */ 547 node_alloc = ump->vtop_alloc[ump->node_part]; 548 if ((node_alloc == UDF_ALLOC_METASEQUENTIAL) || 549 (node_alloc == UDF_ALLOC_METABITMAP)) { 550 udf_check_track_metadata_overlap(ump, &trackinfo); 551 } else { 552 ump->metadata_track = trackinfo; 553 } 554 } 555 556 if ((ump->data_track.flags & MMC_TRACKINFO_NWA_VALID) == 0) 557 return EROFS; 558 559 if ((ump->metadata_track.flags & MMC_TRACKINFO_NWA_VALID) == 0) 560 return EROFS; 561 562 return 0; 563 } 564 565 /* --------------------------------------------------------------------- */ 566 567 /* 568 * Check if the blob starts with a good UDF tag. Tags are protected by a 569 * checksum over the reader except one byte at position 4 that is the checksum 570 * itself. 571 */ 572 573 int 574 udf_check_tag(void *blob) 575 { 576 struct desc_tag *tag = blob; 577 uint8_t *pos, sum, cnt; 578 579 /* check TAG header checksum */ 580 pos = (uint8_t *) tag; 581 sum = 0; 582 583 for(cnt = 0; cnt < 16; cnt++) { 584 if (cnt != 4) 585 sum += *pos; 586 pos++; 587 } 588 if (sum != tag->cksum) { 589 /* bad tag header checksum; this is not a valid tag */ 590 return EINVAL; 591 } 592 593 return 0; 594 } 595 596 597 /* 598 * check tag payload will check descriptor CRC as specified. 599 * If the descriptor is too long, it will return EIO otherwise EINVAL. 600 */ 601 602 int 603 udf_check_tag_payload(void *blob, uint32_t max_length) 604 { 605 struct desc_tag *tag = blob; 606 uint16_t crc, crc_len; 607 608 crc_len = udf_rw16(tag->desc_crc_len); 609 610 /* check payload CRC if applicable */ 611 if (crc_len == 0) 612 return 0; 613 614 if (crc_len > max_length) 615 return EIO; 616 617 crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH, crc_len); 618 if (crc != udf_rw16(tag->desc_crc)) { 619 /* bad payload CRC; this is a broken tag */ 620 return EINVAL; 621 } 622 623 return 0; 624 } 625 626 627 void 628 udf_validate_tag_sum(void *blob) 629 { 630 struct desc_tag *tag = blob; 631 uint8_t *pos, sum, cnt; 632 633 /* calculate TAG header checksum */ 634 pos = (uint8_t *) tag; 635 sum = 0; 636 637 for(cnt = 0; cnt < 16; cnt++) { 638 if (cnt != 4) sum += *pos; 639 pos++; 640 } 641 tag->cksum = sum; /* 8 bit */ 642 } 643 644 645 /* assumes sector number of descriptor to be saved already present */ 646 void 647 udf_validate_tag_and_crc_sums(void *blob) 648 { 649 struct desc_tag *tag = blob; 650 uint8_t *btag = (uint8_t *) tag; 651 uint16_t crc, crc_len; 652 653 crc_len = udf_rw16(tag->desc_crc_len); 654 655 /* check payload CRC if applicable */ 656 if (crc_len > 0) { 657 crc = udf_cksum(btag + UDF_DESC_TAG_LENGTH, crc_len); 658 tag->desc_crc = udf_rw16(crc); 659 } 660 661 /* calculate TAG header checksum */ 662 udf_validate_tag_sum(blob); 663 } 664 665 /* --------------------------------------------------------------------- */ 666 667 /* 668 * XXX note the different semantics from udfclient: for FIDs it still rounds 669 * up to sectors. Use udf_fidsize() for a correct length. 670 */ 671 672 int 673 udf_tagsize(union dscrptr *dscr, uint32_t lb_size) 674 { 675 uint32_t size, tag_id, num_lb, elmsz; 676 677 tag_id = udf_rw16(dscr->tag.id); 678 679 switch (tag_id) { 680 case TAGID_LOGVOL : 681 size = sizeof(struct logvol_desc) - 1; 682 size += udf_rw32(dscr->lvd.mt_l); 683 break; 684 case TAGID_UNALLOC_SPACE : 685 elmsz = sizeof(struct extent_ad); 686 size = sizeof(struct unalloc_sp_desc) - elmsz; 687 size += udf_rw32(dscr->usd.alloc_desc_num) * elmsz; 688 break; 689 case TAGID_FID : 690 size = UDF_FID_SIZE + dscr->fid.l_fi + udf_rw16(dscr->fid.l_iu); 691 size = (size + 3) & ~3; 692 break; 693 case TAGID_LOGVOL_INTEGRITY : 694 size = sizeof(struct logvol_int_desc) - sizeof(uint32_t); 695 size += udf_rw32(dscr->lvid.l_iu); 696 size += (2 * udf_rw32(dscr->lvid.num_part) * sizeof(uint32_t)); 697 break; 698 case TAGID_SPACE_BITMAP : 699 size = sizeof(struct space_bitmap_desc) - 1; 700 size += udf_rw32(dscr->sbd.num_bytes); 701 break; 702 case TAGID_SPARING_TABLE : 703 elmsz = sizeof(struct spare_map_entry); 704 size = sizeof(struct udf_sparing_table) - elmsz; 705 size += udf_rw16(dscr->spt.rt_l) * elmsz; 706 break; 707 case TAGID_FENTRY : 708 size = sizeof(struct file_entry); 709 size += udf_rw32(dscr->fe.l_ea) + udf_rw32(dscr->fe.l_ad)-1; 710 break; 711 case TAGID_EXTFENTRY : 712 size = sizeof(struct extfile_entry); 713 size += udf_rw32(dscr->efe.l_ea) + udf_rw32(dscr->efe.l_ad)-1; 714 break; 715 case TAGID_FSD : 716 size = sizeof(struct fileset_desc); 717 break; 718 default : 719 size = sizeof(union dscrptr); 720 break; 721 } 722 723 if ((size == 0) || (lb_size == 0)) 724 return 0; 725 726 if (lb_size == 1) 727 return size; 728 729 /* round up in sectors */ 730 num_lb = (size + lb_size -1) / lb_size; 731 return num_lb * lb_size; 732 } 733 734 735 int 736 udf_fidsize(struct fileid_desc *fid) 737 { 738 uint32_t size; 739 740 if (udf_rw16(fid->tag.id) != TAGID_FID) 741 panic("got udf_fidsize on non FID\n"); 742 743 size = UDF_FID_SIZE + fid->l_fi + udf_rw16(fid->l_iu); 744 size = (size + 3) & ~3; 745 746 return size; 747 } 748 749 /* --------------------------------------------------------------------- */ 750 751 void 752 udf_lock_node(struct udf_node *udf_node, int flag, char const *fname, const int lineno) 753 { 754 int ret; 755 756 mutex_enter(&udf_node->node_mutex); 757 /* wait until free */ 758 while (udf_node->i_flags & IN_LOCKED) { 759 ret = cv_timedwait(&udf_node->node_lock, &udf_node->node_mutex, hz/8); 760 /* TODO check if we should return error; abort */ 761 if (ret == EWOULDBLOCK) { 762 DPRINTF(LOCKING, ( "udf_lock_node: udf_node %p would block " 763 "wanted at %s:%d, previously locked at %s:%d\n", 764 udf_node, fname, lineno, 765 udf_node->lock_fname, udf_node->lock_lineno)); 766 } 767 } 768 /* grab */ 769 udf_node->i_flags |= IN_LOCKED | flag; 770 /* debug */ 771 udf_node->lock_fname = fname; 772 udf_node->lock_lineno = lineno; 773 774 mutex_exit(&udf_node->node_mutex); 775 } 776 777 778 void 779 udf_unlock_node(struct udf_node *udf_node, int flag) 780 { 781 mutex_enter(&udf_node->node_mutex); 782 udf_node->i_flags &= ~(IN_LOCKED | flag); 783 cv_broadcast(&udf_node->node_lock); 784 mutex_exit(&udf_node->node_mutex); 785 } 786 787 788 /* --------------------------------------------------------------------- */ 789 790 static int 791 udf_read_anchor(struct udf_mount *ump, uint32_t sector, struct anchor_vdp **dst) 792 { 793 int error; 794 795 error = udf_read_phys_dscr(ump, sector, M_UDFVOLD, 796 (union dscrptr **) dst); 797 if (!error) { 798 /* blank terminator blocks are not allowed here */ 799 if (*dst == NULL) 800 return ENOENT; 801 if (udf_rw16((*dst)->tag.id) != TAGID_ANCHOR) { 802 error = ENOENT; 803 free(*dst, M_UDFVOLD); 804 *dst = NULL; 805 DPRINTF(VOLUMES, ("Not an anchor\n")); 806 } 807 } 808 809 return error; 810 } 811 812 813 int 814 udf_read_anchors(struct udf_mount *ump) 815 { 816 struct udf_args *args = &ump->mount_args; 817 struct mmc_trackinfo first_track; 818 struct mmc_trackinfo second_track; 819 struct mmc_trackinfo last_track; 820 struct anchor_vdp **anchorsp; 821 uint32_t track_start; 822 uint32_t track_end; 823 uint32_t positions[4]; 824 int first_tracknr, last_tracknr; 825 int error, anch, ok, first_anchor; 826 827 /* search the first and last track of the specified session */ 828 error = udf_search_tracks(ump, args, &first_tracknr, &last_tracknr); 829 if (!error) { 830 first_track.tracknr = first_tracknr; 831 error = udf_update_trackinfo(ump, &first_track); 832 } 833 if (!error) { 834 last_track.tracknr = last_tracknr; 835 error = udf_update_trackinfo(ump, &last_track); 836 } 837 if ((!error) && (first_tracknr != last_tracknr)) { 838 second_track.tracknr = first_tracknr+1; 839 error = udf_update_trackinfo(ump, &second_track); 840 } 841 if (error) { 842 printf("UDF mount: reading disc geometry failed\n"); 843 return 0; 844 } 845 846 track_start = first_track.track_start; 847 848 /* `end' is not as straitforward as start. */ 849 track_end = last_track.track_start 850 + last_track.track_size - last_track.free_blocks - 1; 851 852 if (ump->discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) { 853 /* end of track is not straitforward here */ 854 if (last_track.flags & MMC_TRACKINFO_LRA_VALID) 855 track_end = last_track.last_recorded; 856 else if (last_track.flags & MMC_TRACKINFO_NWA_VALID) 857 track_end = last_track.next_writable 858 - ump->discinfo.link_block_penalty; 859 } 860 861 /* its no use reading a blank track */ 862 first_anchor = 0; 863 if (first_track.flags & MMC_TRACKINFO_BLANK) 864 first_anchor = 1; 865 866 /* get our packet size */ 867 ump->packet_size = first_track.packet_size; 868 if (first_track.flags & MMC_TRACKINFO_BLANK) 869 ump->packet_size = second_track.packet_size; 870 871 if (ump->packet_size <= 1) { 872 /* take max, but not bigger than 64 */ 873 ump->packet_size = MAXPHYS / ump->discinfo.sector_size; 874 ump->packet_size = MIN(ump->packet_size, 64); 875 } 876 KASSERT(ump->packet_size >= 1); 877 878 /* read anchors start+256, start+512, end-256, end */ 879 positions[0] = track_start+256; 880 positions[1] = track_end-256; 881 positions[2] = track_end; 882 positions[3] = track_start+512; /* [UDF 2.60/6.11.2] */ 883 /* XXX shouldn't +512 be prefered above +256 for compat with Roxio CD */ 884 885 ok = 0; 886 anchorsp = ump->anchors; 887 for (anch = first_anchor; anch < 4; anch++) { 888 DPRINTF(VOLUMES, ("Read anchor %d at sector %d\n", anch, 889 positions[anch])); 890 error = udf_read_anchor(ump, positions[anch], anchorsp); 891 if (!error) { 892 anchorsp++; 893 ok++; 894 } 895 } 896 897 /* VATs are only recorded on sequential media, but initialise */ 898 ump->first_possible_vat_location = track_start + 2; 899 ump->last_possible_vat_location = track_end + last_track.packet_size; 900 901 return ok; 902 } 903 904 /* --------------------------------------------------------------------- */ 905 906 /* we dont try to be smart; we just record the parts */ 907 #define UDF_UPDATE_DSCR(name, dscr) \ 908 if (name) \ 909 free(name, M_UDFVOLD); \ 910 name = dscr; 911 912 static int 913 udf_process_vds_descriptor(struct udf_mount *ump, union dscrptr *dscr) 914 { 915 struct part_desc *part; 916 uint16_t phys_part, raw_phys_part; 917 918 DPRINTF(VOLUMES, ("\tprocessing VDS descr %d\n", 919 udf_rw16(dscr->tag.id))); 920 switch (udf_rw16(dscr->tag.id)) { 921 case TAGID_PRI_VOL : /* primary partition */ 922 UDF_UPDATE_DSCR(ump->primary_vol, &dscr->pvd); 923 break; 924 case TAGID_LOGVOL : /* logical volume */ 925 UDF_UPDATE_DSCR(ump->logical_vol, &dscr->lvd); 926 break; 927 case TAGID_UNALLOC_SPACE : /* unallocated space */ 928 UDF_UPDATE_DSCR(ump->unallocated, &dscr->usd); 929 break; 930 case TAGID_IMP_VOL : /* implementation */ 931 /* XXX do we care about multiple impl. descr ? */ 932 UDF_UPDATE_DSCR(ump->implementation, &dscr->ivd); 933 break; 934 case TAGID_PARTITION : /* physical partition */ 935 /* not much use if its not allocated */ 936 if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) { 937 free(dscr, M_UDFVOLD); 938 break; 939 } 940 941 /* 942 * BUGALERT: some rogue implementations use random physical 943 * partion numbers to break other implementations so lookup 944 * the number. 945 */ 946 raw_phys_part = udf_rw16(dscr->pd.part_num); 947 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 948 part = ump->partitions[phys_part]; 949 if (part == NULL) 950 break; 951 if (udf_rw16(part->part_num) == raw_phys_part) 952 break; 953 } 954 if (phys_part == UDF_PARTITIONS) { 955 free(dscr, M_UDFVOLD); 956 return EINVAL; 957 } 958 959 UDF_UPDATE_DSCR(ump->partitions[phys_part], &dscr->pd); 960 break; 961 case TAGID_VOL : /* volume space extender; rare */ 962 DPRINTF(VOLUMES, ("VDS extender ignored\n")); 963 free(dscr, M_UDFVOLD); 964 break; 965 default : 966 DPRINTF(VOLUMES, ("Unhandled VDS type %d\n", 967 udf_rw16(dscr->tag.id))); 968 free(dscr, M_UDFVOLD); 969 } 970 971 return 0; 972 } 973 #undef UDF_UPDATE_DSCR 974 975 /* --------------------------------------------------------------------- */ 976 977 static int 978 udf_read_vds_extent(struct udf_mount *ump, uint32_t loc, uint32_t len) 979 { 980 union dscrptr *dscr; 981 uint32_t sector_size, dscr_size; 982 int error; 983 984 sector_size = ump->discinfo.sector_size; 985 986 /* loc is sectornr, len is in bytes */ 987 error = EIO; 988 while (len) { 989 error = udf_read_phys_dscr(ump, loc, M_UDFVOLD, &dscr); 990 if (error) 991 return error; 992 993 /* blank block is a terminator */ 994 if (dscr == NULL) 995 return 0; 996 997 /* TERM descriptor is a terminator */ 998 if (udf_rw16(dscr->tag.id) == TAGID_TERM) { 999 free(dscr, M_UDFVOLD); 1000 return 0; 1001 } 1002 1003 /* process all others */ 1004 dscr_size = udf_tagsize(dscr, sector_size); 1005 error = udf_process_vds_descriptor(ump, dscr); 1006 if (error) { 1007 free(dscr, M_UDFVOLD); 1008 break; 1009 } 1010 assert((dscr_size % sector_size) == 0); 1011 1012 len -= dscr_size; 1013 loc += dscr_size / sector_size; 1014 } 1015 1016 return error; 1017 } 1018 1019 1020 int 1021 udf_read_vds_space(struct udf_mount *ump) 1022 { 1023 /* struct udf_args *args = &ump->mount_args; */ 1024 struct anchor_vdp *anchor, *anchor2; 1025 size_t size; 1026 uint32_t main_loc, main_len; 1027 uint32_t reserve_loc, reserve_len; 1028 int error; 1029 1030 /* 1031 * read in VDS space provided by the anchors; if one descriptor read 1032 * fails, try the mirror sector. 1033 * 1034 * check if 2nd anchor is different from 1st; if so, go for 2nd. This 1035 * avoids the `compatibility features' of DirectCD that may confuse 1036 * stuff completely. 1037 */ 1038 1039 anchor = ump->anchors[0]; 1040 anchor2 = ump->anchors[1]; 1041 assert(anchor); 1042 1043 if (anchor2) { 1044 size = sizeof(struct extent_ad); 1045 if (memcmp(&anchor->main_vds_ex, &anchor2->main_vds_ex, size)) 1046 anchor = anchor2; 1047 /* reserve is specified to be a literal copy of main */ 1048 } 1049 1050 main_loc = udf_rw32(anchor->main_vds_ex.loc); 1051 main_len = udf_rw32(anchor->main_vds_ex.len); 1052 1053 reserve_loc = udf_rw32(anchor->reserve_vds_ex.loc); 1054 reserve_len = udf_rw32(anchor->reserve_vds_ex.len); 1055 1056 error = udf_read_vds_extent(ump, main_loc, main_len); 1057 if (error) { 1058 printf("UDF mount: reading in reserve VDS extent\n"); 1059 error = udf_read_vds_extent(ump, reserve_loc, reserve_len); 1060 } 1061 1062 return error; 1063 } 1064 1065 /* --------------------------------------------------------------------- */ 1066 1067 /* 1068 * Read in the logical volume integrity sequence pointed to by our logical 1069 * volume descriptor. Its a sequence that can be extended using fields in the 1070 * integrity descriptor itself. On sequential media only one is found, on 1071 * rewritable media a sequence of descriptors can be found as a form of 1072 * history keeping and on non sequential write-once media the chain is vital 1073 * to allow more and more descriptors to be written. The last descriptor 1074 * written in an extent needs to claim space for a new extent. 1075 */ 1076 1077 static int 1078 udf_retrieve_lvint(struct udf_mount *ump) 1079 { 1080 union dscrptr *dscr; 1081 struct logvol_int_desc *lvint; 1082 struct udf_lvintq *trace; 1083 uint32_t lb_size, lbnum, len; 1084 int dscr_type, error, trace_len; 1085 1086 lb_size = udf_rw32(ump->logical_vol->lb_size); 1087 len = udf_rw32(ump->logical_vol->integrity_seq_loc.len); 1088 lbnum = udf_rw32(ump->logical_vol->integrity_seq_loc.loc); 1089 1090 /* clean trace */ 1091 memset(ump->lvint_trace, 0, 1092 UDF_LVDINT_SEGMENTS * sizeof(struct udf_lvintq)); 1093 1094 trace_len = 0; 1095 trace = ump->lvint_trace; 1096 trace->start = lbnum; 1097 trace->end = lbnum + len/lb_size; 1098 trace->pos = 0; 1099 trace->wpos = 0; 1100 1101 lvint = NULL; 1102 dscr = NULL; 1103 error = 0; 1104 while (len) { 1105 trace->pos = lbnum - trace->start; 1106 trace->wpos = trace->pos + 1; 1107 1108 /* read in our integrity descriptor */ 1109 error = udf_read_phys_dscr(ump, lbnum, M_UDFVOLD, &dscr); 1110 if (!error) { 1111 if (dscr == NULL) { 1112 trace->wpos = trace->pos; 1113 break; /* empty terminates */ 1114 } 1115 dscr_type = udf_rw16(dscr->tag.id); 1116 if (dscr_type == TAGID_TERM) { 1117 trace->wpos = trace->pos; 1118 break; /* clean terminator */ 1119 } 1120 if (dscr_type != TAGID_LOGVOL_INTEGRITY) { 1121 /* fatal... corrupt disc */ 1122 error = ENOENT; 1123 break; 1124 } 1125 if (lvint) 1126 free(lvint, M_UDFVOLD); 1127 lvint = &dscr->lvid; 1128 dscr = NULL; 1129 } /* else hope for the best... maybe the next is ok */ 1130 1131 DPRINTFIF(VOLUMES, lvint, ("logvol integrity read, state %s\n", 1132 udf_rw32(lvint->integrity_type) ? "CLOSED" : "OPEN")); 1133 1134 /* proceed sequential */ 1135 lbnum += 1; 1136 len -= lb_size; 1137 1138 /* are we linking to a new piece? */ 1139 if (dscr && lvint->next_extent.len) { 1140 len = udf_rw32(lvint->next_extent.len); 1141 lbnum = udf_rw32(lvint->next_extent.loc); 1142 1143 if (trace_len >= UDF_LVDINT_SEGMENTS-1) { 1144 /* IEK! segment link full... */ 1145 DPRINTF(VOLUMES, ("lvdint segments full\n")); 1146 error = EINVAL; 1147 } else { 1148 trace++; 1149 trace_len++; 1150 1151 trace->start = lbnum; 1152 trace->end = lbnum + len/lb_size; 1153 trace->pos = 0; 1154 trace->wpos = 0; 1155 } 1156 } 1157 } 1158 1159 /* clean up the mess, esp. when there is an error */ 1160 if (dscr) 1161 free(dscr, M_UDFVOLD); 1162 1163 if (error && lvint) { 1164 free(lvint, M_UDFVOLD); 1165 lvint = NULL; 1166 } 1167 1168 if (!lvint) 1169 error = ENOENT; 1170 1171 ump->logvol_integrity = lvint; 1172 return error; 1173 } 1174 1175 1176 static int 1177 udf_loose_lvint_history(struct udf_mount *ump) 1178 { 1179 union dscrptr **bufs, *dscr, *last_dscr; 1180 struct udf_lvintq *trace, *in_trace, *out_trace; 1181 struct logvol_int_desc *lvint; 1182 uint32_t in_ext, in_pos, in_len; 1183 uint32_t out_ext, out_wpos, out_len; 1184 uint32_t lb_size, packet_size, lb_num; 1185 uint32_t len, start; 1186 int ext, minext, extlen, cnt, cpy_len, dscr_type; 1187 int losing; 1188 int error; 1189 1190 DPRINTF(VOLUMES, ("need to lose some lvint history\n")); 1191 1192 lb_size = udf_rw32(ump->logical_vol->lb_size); 1193 packet_size = ump->data_track.packet_size; /* XXX data track */ 1194 1195 /* search smallest extent */ 1196 trace = &ump->lvint_trace[0]; 1197 minext = trace->end - trace->start; 1198 for (ext = 1; ext < UDF_LVDINT_SEGMENTS; ext++) { 1199 trace = &ump->lvint_trace[ext]; 1200 extlen = trace->end - trace->start; 1201 if (extlen == 0) 1202 break; 1203 minext = MIN(minext, extlen); 1204 } 1205 losing = MIN(minext, UDF_LVINT_LOSSAGE); 1206 /* no sense wiping all */ 1207 if (losing == minext) 1208 losing--; 1209 1210 DPRINTF(VOLUMES, ("\tlosing %d entries\n", losing)); 1211 1212 /* get buffer for pieces */ 1213 bufs = malloc(UDF_LVDINT_SEGMENTS * sizeof(void *), M_TEMP, M_WAITOK); 1214 1215 in_ext = 0; 1216 in_pos = losing; 1217 in_trace = &ump->lvint_trace[in_ext]; 1218 in_len = in_trace->end - in_trace->start; 1219 out_ext = 0; 1220 out_wpos = 0; 1221 out_trace = &ump->lvint_trace[out_ext]; 1222 out_len = out_trace->end - out_trace->start; 1223 1224 last_dscr = NULL; 1225 for(;;) { 1226 out_trace->pos = out_wpos; 1227 out_trace->wpos = out_trace->pos; 1228 if (in_pos >= in_len) { 1229 in_ext++; 1230 in_pos = 0; 1231 in_trace = &ump->lvint_trace[in_ext]; 1232 in_len = in_trace->end - in_trace->start; 1233 } 1234 if (out_wpos >= out_len) { 1235 out_ext++; 1236 out_wpos = 0; 1237 out_trace = &ump->lvint_trace[out_ext]; 1238 out_len = out_trace->end - out_trace->start; 1239 } 1240 /* copy overlap contents */ 1241 cpy_len = MIN(in_len - in_pos, out_len - out_wpos); 1242 cpy_len = MIN(cpy_len, in_len - in_trace->pos); 1243 if (cpy_len == 0) 1244 break; 1245 1246 /* copy */ 1247 DPRINTF(VOLUMES, ("\treading %d lvid descriptors\n", cpy_len)); 1248 for (cnt = 0; cnt < cpy_len; cnt++) { 1249 /* read in our integrity descriptor */ 1250 lb_num = in_trace->start + in_pos + cnt; 1251 error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, 1252 &dscr); 1253 if (error) { 1254 /* copy last one */ 1255 dscr = last_dscr; 1256 } 1257 bufs[cnt] = dscr; 1258 if (!error) { 1259 if (dscr == NULL) { 1260 out_trace->pos = out_wpos + cnt; 1261 out_trace->wpos = out_trace->pos; 1262 break; /* empty terminates */ 1263 } 1264 dscr_type = udf_rw16(dscr->tag.id); 1265 if (dscr_type == TAGID_TERM) { 1266 out_trace->pos = out_wpos + cnt; 1267 out_trace->wpos = out_trace->pos; 1268 break; /* clean terminator */ 1269 } 1270 if (dscr_type != TAGID_LOGVOL_INTEGRITY) { 1271 panic( "UDF integrity sequence " 1272 "corrupted while mounted!\n"); 1273 } 1274 last_dscr = dscr; 1275 } 1276 } 1277 1278 /* patch up if first entry was on error */ 1279 if (bufs[0] == NULL) { 1280 for (cnt = 0; cnt < cpy_len; cnt++) 1281 if (bufs[cnt] != NULL) 1282 break; 1283 last_dscr = bufs[cnt]; 1284 for (; cnt > 0; cnt--) { 1285 bufs[cnt] = last_dscr; 1286 } 1287 } 1288 1289 /* glue + write out */ 1290 DPRINTF(VOLUMES, ("\twriting %d lvid descriptors\n", cpy_len)); 1291 for (cnt = 0; cnt < cpy_len; cnt++) { 1292 lb_num = out_trace->start + out_wpos + cnt; 1293 lvint = &bufs[cnt]->lvid; 1294 1295 /* set continuation */ 1296 len = 0; 1297 start = 0; 1298 if (out_wpos + cnt == out_len) { 1299 /* get continuation */ 1300 trace = &ump->lvint_trace[out_ext+1]; 1301 len = trace->end - trace->start; 1302 start = trace->start; 1303 } 1304 lvint->next_extent.len = udf_rw32(len); 1305 lvint->next_extent.loc = udf_rw32(start); 1306 1307 lb_num = trace->start + trace->wpos; 1308 error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 1309 bufs[cnt], lb_num, lb_num); 1310 DPRINTFIF(VOLUMES, error, 1311 ("error writing lvint lb_num\n")); 1312 } 1313 1314 /* free non repeating descriptors */ 1315 last_dscr = NULL; 1316 for (cnt = 0; cnt < cpy_len; cnt++) { 1317 if (bufs[cnt] != last_dscr) 1318 free(bufs[cnt], M_UDFVOLD); 1319 last_dscr = bufs[cnt]; 1320 } 1321 1322 /* advance */ 1323 in_pos += cpy_len; 1324 out_wpos += cpy_len; 1325 } 1326 1327 free(bufs, M_TEMP); 1328 1329 return 0; 1330 } 1331 1332 1333 static int 1334 udf_writeout_lvint(struct udf_mount *ump, int lvflag) 1335 { 1336 struct udf_lvintq *trace; 1337 struct timeval now_v; 1338 struct timespec now_s; 1339 uint32_t sector; 1340 int logvol_integrity; 1341 int space, error; 1342 1343 DPRINTF(VOLUMES, ("writing out logvol integrity descriptor\n")); 1344 1345 again: 1346 /* get free space in last chunk */ 1347 trace = ump->lvint_trace; 1348 while (trace->wpos > (trace->end - trace->start)) { 1349 DPRINTF(VOLUMES, ("skip : start = %d, end = %d, pos = %d, " 1350 "wpos = %d\n", trace->start, trace->end, 1351 trace->pos, trace->wpos)); 1352 trace++; 1353 } 1354 1355 /* check if there is space to append */ 1356 space = (trace->end - trace->start) - trace->wpos; 1357 DPRINTF(VOLUMES, ("write start = %d, end = %d, pos = %d, wpos = %d, " 1358 "space = %d\n", trace->start, trace->end, trace->pos, 1359 trace->wpos, space)); 1360 1361 /* get state */ 1362 logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type); 1363 if (logvol_integrity == UDF_INTEGRITY_CLOSED) { 1364 if ((space < 3) && (lvflag & UDF_APPENDONLY_LVINT)) { 1365 /* don't allow this logvol to be opened */ 1366 /* TODO extent LVINT space if possible */ 1367 return EROFS; 1368 } 1369 } 1370 1371 if (space < 1) { 1372 if (lvflag & UDF_APPENDONLY_LVINT) 1373 return EROFS; 1374 /* loose history by re-writing extents */ 1375 error = udf_loose_lvint_history(ump); 1376 if (error) 1377 return error; 1378 goto again; 1379 } 1380 1381 /* update our integrity descriptor to identify us and timestamp it */ 1382 DPRINTF(VOLUMES, ("updating integrity descriptor\n")); 1383 microtime(&now_v); 1384 TIMEVAL_TO_TIMESPEC(&now_v, &now_s); 1385 udf_timespec_to_timestamp(&now_s, &ump->logvol_integrity->time); 1386 udf_set_regid(&ump->logvol_info->impl_id, IMPL_NAME); 1387 udf_add_impl_regid(ump, &ump->logvol_info->impl_id); 1388 1389 /* writeout integrity descriptor */ 1390 sector = trace->start + trace->wpos; 1391 error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 1392 (union dscrptr *) ump->logvol_integrity, 1393 sector, sector); 1394 DPRINTF(VOLUMES, ("writeout lvint : error = %d\n", error)); 1395 if (error) 1396 return error; 1397 1398 /* advance write position */ 1399 trace->wpos++; space--; 1400 if (space >= 1) { 1401 /* append terminator */ 1402 sector = trace->start + trace->wpos; 1403 error = udf_write_terminator(ump, sector); 1404 1405 DPRINTF(VOLUMES, ("write terminator : error = %d\n", error)); 1406 } 1407 1408 space = (trace->end - trace->start) - trace->wpos; 1409 DPRINTF(VOLUMES, ("write start = %d, end = %d, pos = %d, wpos = %d, " 1410 "space = %d\n", trace->start, trace->end, trace->pos, 1411 trace->wpos, space)); 1412 DPRINTF(VOLUMES, ("finished writing out logvol integrity descriptor " 1413 "successfull\n")); 1414 1415 return error; 1416 } 1417 1418 /* --------------------------------------------------------------------- */ 1419 1420 static int 1421 udf_read_physical_partition_spacetables(struct udf_mount *ump) 1422 { 1423 union dscrptr *dscr; 1424 /* struct udf_args *args = &ump->mount_args; */ 1425 struct part_desc *partd; 1426 struct part_hdr_desc *parthdr; 1427 struct udf_bitmap *bitmap; 1428 uint32_t phys_part; 1429 uint32_t lb_num, len; 1430 int error, dscr_type; 1431 1432 /* unallocated space map */ 1433 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1434 partd = ump->partitions[phys_part]; 1435 if (partd == NULL) 1436 continue; 1437 parthdr = &partd->_impl_use.part_hdr; 1438 1439 lb_num = udf_rw32(partd->start_loc); 1440 lb_num += udf_rw32(parthdr->unalloc_space_bitmap.lb_num); 1441 len = udf_rw32(parthdr->unalloc_space_bitmap.len); 1442 if (len == 0) 1443 continue; 1444 1445 DPRINTF(VOLUMES, ("Read unalloc. space bitmap %d\n", lb_num)); 1446 error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr); 1447 if (!error && dscr) { 1448 /* analyse */ 1449 dscr_type = udf_rw16(dscr->tag.id); 1450 if (dscr_type == TAGID_SPACE_BITMAP) { 1451 DPRINTF(VOLUMES, ("Accepting space bitmap\n")); 1452 ump->part_unalloc_dscr[phys_part] = &dscr->sbd; 1453 1454 /* fill in ump->part_unalloc_bits */ 1455 bitmap = &ump->part_unalloc_bits[phys_part]; 1456 bitmap->blob = (uint8_t *) dscr; 1457 bitmap->bits = dscr->sbd.data; 1458 bitmap->max_offset = udf_rw32(dscr->sbd.num_bits); 1459 bitmap->pages = NULL; /* TODO */ 1460 bitmap->data_pos = 0; 1461 bitmap->metadata_pos = 0; 1462 } else { 1463 free(dscr, M_UDFVOLD); 1464 1465 printf( "UDF mount: error reading unallocated " 1466 "space bitmap\n"); 1467 return EROFS; 1468 } 1469 } else { 1470 /* blank not allowed */ 1471 printf("UDF mount: blank unallocated space bitmap\n"); 1472 return EROFS; 1473 } 1474 } 1475 1476 /* unallocated space table (not supported) */ 1477 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1478 partd = ump->partitions[phys_part]; 1479 if (partd == NULL) 1480 continue; 1481 parthdr = &partd->_impl_use.part_hdr; 1482 1483 len = udf_rw32(parthdr->unalloc_space_table.len); 1484 if (len) { 1485 printf("UDF mount: space tables not supported\n"); 1486 return EROFS; 1487 } 1488 } 1489 1490 /* freed space map */ 1491 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1492 partd = ump->partitions[phys_part]; 1493 if (partd == NULL) 1494 continue; 1495 parthdr = &partd->_impl_use.part_hdr; 1496 1497 /* freed space map */ 1498 lb_num = udf_rw32(partd->start_loc); 1499 lb_num += udf_rw32(parthdr->freed_space_bitmap.lb_num); 1500 len = udf_rw32(parthdr->freed_space_bitmap.len); 1501 if (len == 0) 1502 continue; 1503 1504 DPRINTF(VOLUMES, ("Read unalloc. space bitmap %d\n", lb_num)); 1505 error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr); 1506 if (!error && dscr) { 1507 /* analyse */ 1508 dscr_type = udf_rw16(dscr->tag.id); 1509 if (dscr_type == TAGID_SPACE_BITMAP) { 1510 DPRINTF(VOLUMES, ("Accepting space bitmap\n")); 1511 ump->part_freed_dscr[phys_part] = &dscr->sbd; 1512 1513 /* fill in ump->part_freed_bits */ 1514 bitmap = &ump->part_unalloc_bits[phys_part]; 1515 bitmap->blob = (uint8_t *) dscr; 1516 bitmap->bits = dscr->sbd.data; 1517 bitmap->max_offset = udf_rw32(dscr->sbd.num_bits); 1518 bitmap->pages = NULL; /* TODO */ 1519 bitmap->data_pos = 0; 1520 bitmap->metadata_pos = 0; 1521 } else { 1522 free(dscr, M_UDFVOLD); 1523 1524 printf( "UDF mount: error reading freed " 1525 "space bitmap\n"); 1526 return EROFS; 1527 } 1528 } else { 1529 /* blank not allowed */ 1530 printf("UDF mount: blank freed space bitmap\n"); 1531 return EROFS; 1532 } 1533 } 1534 1535 /* freed space table (not supported) */ 1536 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1537 partd = ump->partitions[phys_part]; 1538 if (partd == NULL) 1539 continue; 1540 parthdr = &partd->_impl_use.part_hdr; 1541 1542 len = udf_rw32(parthdr->freed_space_table.len); 1543 if (len) { 1544 printf("UDF mount: space tables not supported\n"); 1545 return EROFS; 1546 } 1547 } 1548 1549 return 0; 1550 } 1551 1552 1553 /* TODO implement async writeout */ 1554 int 1555 udf_write_physical_partition_spacetables(struct udf_mount *ump, int waitfor) 1556 { 1557 union dscrptr *dscr; 1558 /* struct udf_args *args = &ump->mount_args; */ 1559 struct part_desc *partd; 1560 struct part_hdr_desc *parthdr; 1561 uint32_t phys_part; 1562 uint32_t lb_num, len, ptov; 1563 int error_all, error; 1564 1565 error_all = 0; 1566 /* unallocated space map */ 1567 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1568 partd = ump->partitions[phys_part]; 1569 if (partd == NULL) 1570 continue; 1571 parthdr = &partd->_impl_use.part_hdr; 1572 1573 ptov = udf_rw32(partd->start_loc); 1574 lb_num = udf_rw32(parthdr->unalloc_space_bitmap.lb_num); 1575 len = udf_rw32(parthdr->unalloc_space_bitmap.len); 1576 if (len == 0) 1577 continue; 1578 1579 DPRINTF(VOLUMES, ("Write unalloc. space bitmap %d\n", 1580 lb_num + ptov)); 1581 dscr = (union dscrptr *) ump->part_unalloc_dscr[phys_part]; 1582 error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 1583 (union dscrptr *) dscr, 1584 ptov + lb_num, lb_num); 1585 if (error) { 1586 DPRINTF(VOLUMES, ("\tfailed!! (error %d)\n", error)); 1587 error_all = error; 1588 } 1589 } 1590 1591 /* freed space map */ 1592 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1593 partd = ump->partitions[phys_part]; 1594 if (partd == NULL) 1595 continue; 1596 parthdr = &partd->_impl_use.part_hdr; 1597 1598 /* freed space map */ 1599 ptov = udf_rw32(partd->start_loc); 1600 lb_num = udf_rw32(parthdr->freed_space_bitmap.lb_num); 1601 len = udf_rw32(parthdr->freed_space_bitmap.len); 1602 if (len == 0) 1603 continue; 1604 1605 DPRINTF(VOLUMES, ("Write freed space bitmap %d\n", 1606 lb_num + ptov)); 1607 dscr = (union dscrptr *) ump->part_freed_dscr[phys_part]; 1608 error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 1609 (union dscrptr *) dscr, 1610 ptov + lb_num, lb_num); 1611 if (error) { 1612 DPRINTF(VOLUMES, ("\tfailed!! (error %d)\n", error)); 1613 error_all = error; 1614 } 1615 } 1616 1617 return error_all; 1618 } 1619 1620 1621 static int 1622 udf_read_metadata_partition_spacetable(struct udf_mount *ump) 1623 { 1624 struct udf_node *bitmap_node; 1625 union dscrptr *dscr; 1626 struct udf_bitmap *bitmap; 1627 uint64_t inflen; 1628 int error, dscr_type; 1629 1630 bitmap_node = ump->metadatabitmap_node; 1631 1632 /* only read in when metadata bitmap node is read in */ 1633 if (bitmap_node == NULL) 1634 return 0; 1635 1636 if (bitmap_node->fe) { 1637 inflen = udf_rw64(bitmap_node->fe->inf_len); 1638 } else { 1639 KASSERT(bitmap_node->efe); 1640 inflen = udf_rw64(bitmap_node->efe->inf_len); 1641 } 1642 1643 DPRINTF(VOLUMES, ("Reading metadata space bitmap for " 1644 "%"PRIu64" bytes\n", inflen)); 1645 1646 /* allocate space for bitmap */ 1647 dscr = malloc(inflen, M_UDFVOLD, M_CANFAIL | M_WAITOK); 1648 if (!dscr) 1649 return ENOMEM; 1650 1651 /* set vnode type to regular file or we can't read from it! */ 1652 bitmap_node->vnode->v_type = VREG; 1653 1654 /* read in complete metadata bitmap file */ 1655 error = vn_rdwr(UIO_READ, bitmap_node->vnode, 1656 dscr, 1657 inflen, 0, 1658 UIO_SYSSPACE, 1659 IO_SYNC | IO_NODELOCKED | IO_ALTSEMANTICS, FSCRED, 1660 NULL, NULL); 1661 if (error) { 1662 DPRINTF(VOLUMES, ("Error reading metadata space bitmap\n")); 1663 goto errorout; 1664 } 1665 1666 /* analyse */ 1667 dscr_type = udf_rw16(dscr->tag.id); 1668 if (dscr_type == TAGID_SPACE_BITMAP) { 1669 DPRINTF(VOLUMES, ("Accepting metadata space bitmap\n")); 1670 ump->metadata_unalloc_dscr = &dscr->sbd; 1671 1672 /* fill in bitmap bits */ 1673 bitmap = &ump->metadata_unalloc_bits; 1674 bitmap->blob = (uint8_t *) dscr; 1675 bitmap->bits = dscr->sbd.data; 1676 bitmap->max_offset = udf_rw32(dscr->sbd.num_bits); 1677 bitmap->pages = NULL; /* TODO */ 1678 bitmap->data_pos = 0; 1679 bitmap->metadata_pos = 0; 1680 } else { 1681 DPRINTF(VOLUMES, ("No valid bitmap found!\n")); 1682 goto errorout; 1683 } 1684 1685 return 0; 1686 1687 errorout: 1688 free(dscr, M_UDFVOLD); 1689 printf( "UDF mount: error reading unallocated " 1690 "space bitmap for metadata partition\n"); 1691 return EROFS; 1692 } 1693 1694 1695 int 1696 udf_write_metadata_partition_spacetable(struct udf_mount *ump, int waitfor) 1697 { 1698 struct udf_node *bitmap_node; 1699 union dscrptr *dscr; 1700 uint64_t inflen, new_inflen; 1701 int dummy, error; 1702 1703 bitmap_node = ump->metadatabitmap_node; 1704 1705 /* only write out when metadata bitmap node is known */ 1706 if (bitmap_node == NULL) 1707 return 0; 1708 1709 if (bitmap_node->fe) { 1710 inflen = udf_rw64(bitmap_node->fe->inf_len); 1711 } else { 1712 KASSERT(bitmap_node->efe); 1713 inflen = udf_rw64(bitmap_node->efe->inf_len); 1714 } 1715 1716 /* reduce length to zero */ 1717 dscr = (union dscrptr *) ump->metadata_unalloc_dscr; 1718 new_inflen = udf_tagsize(dscr, 1); 1719 1720 DPRINTF(VOLUMES, ("Resize and write out metadata space bitmap from " 1721 "%"PRIu64" to %"PRIu64" bytes\n", inflen, new_inflen)); 1722 1723 error = udf_resize_node(bitmap_node, new_inflen, &dummy); 1724 if (error) 1725 printf("Error resizing metadata space bitmap\n"); 1726 1727 error = vn_rdwr(UIO_WRITE, bitmap_node->vnode, 1728 dscr, 1729 new_inflen, 0, 1730 UIO_SYSSPACE, 1731 IO_NODELOCKED | IO_ALTSEMANTICS, FSCRED, 1732 NULL, NULL); 1733 1734 bitmap_node->i_flags |= IN_MODIFIED; 1735 vflushbuf(bitmap_node->vnode, 1 /* sync */); 1736 1737 error = VOP_FSYNC(bitmap_node->vnode, 1738 FSCRED, FSYNC_WAIT, 0, 0); 1739 1740 if (error) 1741 printf( "Error writing out metadata partition unalloced " 1742 "space bitmap!\n"); 1743 1744 return error; 1745 } 1746 1747 1748 /* --------------------------------------------------------------------- */ 1749 1750 /* 1751 * Checks if ump's vds information is correct and complete 1752 */ 1753 1754 int 1755 udf_process_vds(struct udf_mount *ump) { 1756 union udf_pmap *mapping; 1757 /* struct udf_args *args = &ump->mount_args; */ 1758 struct logvol_int_desc *lvint; 1759 struct udf_logvol_info *lvinfo; 1760 struct part_desc *part; 1761 uint32_t n_pm, mt_l; 1762 uint8_t *pmap_pos; 1763 char *domain_name, *map_name; 1764 const char *check_name; 1765 char bits[128]; 1766 int pmap_stype, pmap_size; 1767 int pmap_type, log_part, phys_part, raw_phys_part, maps_on; 1768 int n_phys, n_virt, n_spar, n_meta; 1769 int len, error; 1770 1771 if (ump == NULL) 1772 return ENOENT; 1773 1774 /* we need at least an anchor (trivial, but for safety) */ 1775 if (ump->anchors[0] == NULL) 1776 return EINVAL; 1777 1778 /* we need at least one primary and one logical volume descriptor */ 1779 if ((ump->primary_vol == NULL) || (ump->logical_vol) == NULL) 1780 return EINVAL; 1781 1782 /* we need at least one partition descriptor */ 1783 if (ump->partitions[0] == NULL) 1784 return EINVAL; 1785 1786 /* check logical volume sector size verses device sector size */ 1787 if (udf_rw32(ump->logical_vol->lb_size) != ump->discinfo.sector_size) { 1788 printf("UDF mount: format violation, lb_size != sector size\n"); 1789 return EINVAL; 1790 } 1791 1792 /* check domain name */ 1793 domain_name = ump->logical_vol->domain_id.id; 1794 if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) { 1795 printf("mount_udf: disc not OSTA UDF Compliant, aborting\n"); 1796 return EINVAL; 1797 } 1798 1799 /* retrieve logical volume integrity sequence */ 1800 error = udf_retrieve_lvint(ump); 1801 1802 /* 1803 * We need at least one logvol integrity descriptor recorded. Note 1804 * that its OK to have an open logical volume integrity here. The VAT 1805 * will close/update the integrity. 1806 */ 1807 if (ump->logvol_integrity == NULL) 1808 return EINVAL; 1809 1810 /* process derived structures */ 1811 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1812 lvint = ump->logvol_integrity; 1813 lvinfo = (struct udf_logvol_info *) (&lvint->tables[2 * n_pm]); 1814 ump->logvol_info = lvinfo; 1815 1816 /* TODO check udf versions? */ 1817 1818 /* 1819 * check logvol mappings: effective virt->log partmap translation 1820 * check and recording of the mapping results. Saves expensive 1821 * strncmp() in tight places. 1822 */ 1823 DPRINTF(VOLUMES, ("checking logvol mappings\n")); 1824 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 1825 mt_l = udf_rw32(ump->logical_vol->mt_l); /* partmaps data length */ 1826 pmap_pos = ump->logical_vol->maps; 1827 1828 if (n_pm > UDF_PMAPS) { 1829 printf("UDF mount: too many mappings\n"); 1830 return EINVAL; 1831 } 1832 1833 /* count types and set partition numbers */ 1834 ump->data_part = ump->node_part = ump->fids_part = 0; 1835 n_phys = n_virt = n_spar = n_meta = 0; 1836 for (log_part = 0; log_part < n_pm; log_part++) { 1837 mapping = (union udf_pmap *) pmap_pos; 1838 pmap_stype = pmap_pos[0]; 1839 pmap_size = pmap_pos[1]; 1840 switch (pmap_stype) { 1841 case 1: /* physical mapping */ 1842 /* volseq = udf_rw16(mapping->pm1.vol_seq_num); */ 1843 raw_phys_part = udf_rw16(mapping->pm1.part_num); 1844 pmap_type = UDF_VTOP_TYPE_PHYS; 1845 n_phys++; 1846 ump->data_part = log_part; 1847 ump->node_part = log_part; 1848 ump->fids_part = log_part; 1849 break; 1850 case 2: /* virtual/sparable/meta mapping */ 1851 map_name = mapping->pm2.part_id.id; 1852 /* volseq = udf_rw16(mapping->pm2.vol_seq_num); */ 1853 raw_phys_part = udf_rw16(mapping->pm2.part_num); 1854 pmap_type = UDF_VTOP_TYPE_UNKNOWN; 1855 len = UDF_REGID_ID_SIZE; 1856 1857 check_name = "*UDF Virtual Partition"; 1858 if (strncmp(map_name, check_name, len) == 0) { 1859 pmap_type = UDF_VTOP_TYPE_VIRT; 1860 n_virt++; 1861 ump->node_part = log_part; 1862 break; 1863 } 1864 check_name = "*UDF Sparable Partition"; 1865 if (strncmp(map_name, check_name, len) == 0) { 1866 pmap_type = UDF_VTOP_TYPE_SPARABLE; 1867 n_spar++; 1868 ump->data_part = log_part; 1869 ump->node_part = log_part; 1870 ump->fids_part = log_part; 1871 break; 1872 } 1873 check_name = "*UDF Metadata Partition"; 1874 if (strncmp(map_name, check_name, len) == 0) { 1875 pmap_type = UDF_VTOP_TYPE_META; 1876 n_meta++; 1877 ump->node_part = log_part; 1878 ump->fids_part = log_part; 1879 break; 1880 } 1881 break; 1882 default: 1883 return EINVAL; 1884 } 1885 1886 /* 1887 * BUGALERT: some rogue implementations use random physical 1888 * partion numbers to break other implementations so lookup 1889 * the number. 1890 */ 1891 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1892 part = ump->partitions[phys_part]; 1893 if (part == NULL) 1894 continue; 1895 if (udf_rw16(part->part_num) == raw_phys_part) 1896 break; 1897 } 1898 1899 DPRINTF(VOLUMES, ("\t%d -> %d(%d) type %d\n", log_part, 1900 raw_phys_part, phys_part, pmap_type)); 1901 1902 if (phys_part == UDF_PARTITIONS) 1903 return EINVAL; 1904 if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) 1905 return EINVAL; 1906 1907 ump->vtop [log_part] = phys_part; 1908 ump->vtop_tp[log_part] = pmap_type; 1909 1910 pmap_pos += pmap_size; 1911 } 1912 /* not winning the beauty contest */ 1913 ump->vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW; 1914 1915 /* test some basic UDF assertions/requirements */ 1916 if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1)) 1917 return EINVAL; 1918 1919 if (n_virt) { 1920 if ((n_phys == 0) || n_spar || n_meta) 1921 return EINVAL; 1922 } 1923 if (n_spar + n_phys == 0) 1924 return EINVAL; 1925 1926 /* select allocation type for each logical partition */ 1927 for (log_part = 0; log_part < n_pm; log_part++) { 1928 maps_on = ump->vtop[log_part]; 1929 switch (ump->vtop_tp[log_part]) { 1930 case UDF_VTOP_TYPE_PHYS : 1931 assert(maps_on == log_part); 1932 ump->vtop_alloc[log_part] = UDF_ALLOC_SPACEMAP; 1933 break; 1934 case UDF_VTOP_TYPE_VIRT : 1935 ump->vtop_alloc[log_part] = UDF_ALLOC_VAT; 1936 ump->vtop_alloc[maps_on] = UDF_ALLOC_SEQUENTIAL; 1937 break; 1938 case UDF_VTOP_TYPE_SPARABLE : 1939 assert(maps_on == log_part); 1940 ump->vtop_alloc[log_part] = UDF_ALLOC_SPACEMAP; 1941 break; 1942 case UDF_VTOP_TYPE_META : 1943 ump->vtop_alloc[log_part] = UDF_ALLOC_METABITMAP; 1944 if (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) { 1945 /* special case for UDF 2.60 */ 1946 ump->vtop_alloc[log_part] = UDF_ALLOC_METASEQUENTIAL; 1947 ump->vtop_alloc[maps_on] = UDF_ALLOC_SEQUENTIAL; 1948 } 1949 break; 1950 default: 1951 panic("bad alloction type in udf's ump->vtop\n"); 1952 } 1953 } 1954 1955 /* determine logical volume open/closure actions */ 1956 if (n_virt) { 1957 ump->lvopen = 0; 1958 if (ump->discinfo.last_session_state == MMC_STATE_CLOSED) 1959 ump->lvopen |= UDF_OPEN_SESSION ; 1960 ump->lvclose = UDF_WRITE_VAT; 1961 if (ump->mount_args.udfmflags & UDFMNT_CLOSESESSION) 1962 ump->lvclose |= UDF_CLOSE_SESSION; 1963 } else { 1964 /* `normal' rewritable or non sequential media */ 1965 ump->lvopen = UDF_WRITE_LVINT; 1966 ump->lvclose = UDF_WRITE_LVINT; 1967 if ((ump->discinfo.mmc_cur & MMC_CAP_REWRITABLE) == 0) 1968 ump->lvopen |= UDF_APPENDONLY_LVINT; 1969 } 1970 1971 /* 1972 * Determine sheduler error behaviour. For virtual partions, update 1973 * the trackinfo; for sparable partitions replace a whole block on the 1974 * sparable table. Allways requeue. 1975 */ 1976 ump->lvreadwrite = 0; 1977 if (n_virt) 1978 ump->lvreadwrite = UDF_UPDATE_TRACKINFO; 1979 if (n_spar) 1980 ump->lvreadwrite = UDF_REMAP_BLOCK; 1981 1982 /* 1983 * Select our sheduler 1984 */ 1985 ump->strategy = &udf_strat_rmw; 1986 if (n_virt || (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)) 1987 ump->strategy = &udf_strat_sequential; 1988 if ((ump->discinfo.mmc_class == MMC_CLASS_DISC) || 1989 (ump->discinfo.mmc_class == MMC_CLASS_UNKN)) 1990 ump->strategy = &udf_strat_direct; 1991 if (n_spar) 1992 ump->strategy = &udf_strat_rmw; 1993 1994 /* print results */ 1995 DPRINTF(VOLUMES, ("\tdata partition %d\n", ump->data_part)); 1996 DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->data_part])); 1997 DPRINTF(VOLUMES, ("\tnode partition %d\n", ump->node_part)); 1998 DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->node_part])); 1999 DPRINTF(VOLUMES, ("\tfids partition %d\n", ump->fids_part)); 2000 DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->fids_part])); 2001 2002 bitmask_snprintf(ump->lvopen, UDFLOGVOL_BITS, bits, sizeof(bits)); 2003 DPRINTF(VOLUMES, ("\tactions on logvol open %s\n", bits)); 2004 bitmask_snprintf(ump->lvclose, UDFLOGVOL_BITS, bits, sizeof(bits)); 2005 DPRINTF(VOLUMES, ("\tactions on logvol close %s\n", bits)); 2006 bitmask_snprintf(ump->lvreadwrite, UDFONERROR_BITS, bits, sizeof(bits)); 2007 DPRINTF(VOLUMES, ("\tactions on logvol errors %s\n", bits)); 2008 2009 DPRINTF(VOLUMES, ("\tselected sheduler `%s`\n", 2010 (ump->strategy == &udf_strat_direct) ? "Direct" : 2011 (ump->strategy == &udf_strat_sequential) ? "Sequential" : 2012 (ump->strategy == &udf_strat_rmw) ? "RMW" : "UNKNOWN!")); 2013 2014 /* signal its OK for now */ 2015 return 0; 2016 } 2017 2018 /* --------------------------------------------------------------------- */ 2019 2020 /* 2021 * Update logical volume name in all structures that keep a record of it. We 2022 * use memmove since each of them might be specified as a source. 2023 * 2024 * Note that it doesn't update the VAT structure! 2025 */ 2026 2027 static void 2028 udf_update_logvolname(struct udf_mount *ump, char *logvol_id) 2029 { 2030 struct logvol_desc *lvd = NULL; 2031 struct fileset_desc *fsd = NULL; 2032 struct udf_lv_info *lvi = NULL; 2033 2034 DPRINTF(VOLUMES, ("Updating logical volume name\n")); 2035 lvd = ump->logical_vol; 2036 fsd = ump->fileset_desc; 2037 if (ump->implementation) 2038 lvi = &ump->implementation->_impl_use.lv_info; 2039 2040 /* logvol's id might be specified as origional so use memmove here */ 2041 memmove(lvd->logvol_id, logvol_id, 128); 2042 if (fsd) 2043 memmove(fsd->logvol_id, logvol_id, 128); 2044 if (lvi) 2045 memmove(lvi->logvol_id, logvol_id, 128); 2046 } 2047 2048 /* --------------------------------------------------------------------- */ 2049 2050 void 2051 udf_inittag(struct udf_mount *ump, struct desc_tag *tag, int tagid, 2052 uint32_t sector) 2053 { 2054 assert(ump->logical_vol); 2055 2056 tag->id = udf_rw16(tagid); 2057 tag->descriptor_ver = ump->logical_vol->tag.descriptor_ver; 2058 tag->cksum = 0; 2059 tag->reserved = 0; 2060 tag->serial_num = ump->logical_vol->tag.serial_num; 2061 tag->tag_loc = udf_rw32(sector); 2062 } 2063 2064 2065 uint64_t 2066 udf_advance_uniqueid(struct udf_mount *ump) 2067 { 2068 uint64_t unique_id; 2069 2070 mutex_enter(&ump->logvol_mutex); 2071 unique_id = udf_rw64(ump->logvol_integrity->lvint_next_unique_id); 2072 if (unique_id < 0x10) 2073 unique_id = 0x10; 2074 ump->logvol_integrity->lvint_next_unique_id = udf_rw64(unique_id + 1); 2075 mutex_exit(&ump->logvol_mutex); 2076 2077 return unique_id; 2078 } 2079 2080 2081 static void 2082 udf_adjust_filecount(struct udf_node *udf_node, int sign) 2083 { 2084 struct udf_mount *ump = udf_node->ump; 2085 uint32_t num_dirs, num_files; 2086 int udf_file_type; 2087 2088 /* get file type */ 2089 if (udf_node->fe) { 2090 udf_file_type = udf_node->fe->icbtag.file_type; 2091 } else { 2092 udf_file_type = udf_node->efe->icbtag.file_type; 2093 } 2094 2095 /* adjust file count */ 2096 mutex_enter(&ump->allocate_mutex); 2097 if (udf_file_type == UDF_ICB_FILETYPE_DIRECTORY) { 2098 num_dirs = udf_rw32(ump->logvol_info->num_directories); 2099 ump->logvol_info->num_directories = 2100 udf_rw32((num_dirs + sign)); 2101 } else { 2102 num_files = udf_rw32(ump->logvol_info->num_files); 2103 ump->logvol_info->num_files = 2104 udf_rw32((num_files + sign)); 2105 } 2106 mutex_exit(&ump->allocate_mutex); 2107 } 2108 2109 2110 void 2111 udf_osta_charset(struct charspec *charspec) 2112 { 2113 bzero(charspec, sizeof(struct charspec)); 2114 charspec->type = 0; 2115 strcpy((char *) charspec->inf, "OSTA Compressed Unicode"); 2116 } 2117 2118 2119 /* first call udf_set_regid and then the suffix */ 2120 void 2121 udf_set_regid(struct regid *regid, char const *name) 2122 { 2123 bzero(regid, sizeof(struct regid)); 2124 regid->flags = 0; /* not dirty and not protected */ 2125 strcpy((char *) regid->id, name); 2126 } 2127 2128 2129 void 2130 udf_add_domain_regid(struct udf_mount *ump, struct regid *regid) 2131 { 2132 uint16_t *ver; 2133 2134 ver = (uint16_t *) regid->id_suffix; 2135 *ver = ump->logvol_info->min_udf_readver; 2136 } 2137 2138 2139 void 2140 udf_add_udf_regid(struct udf_mount *ump, struct regid *regid) 2141 { 2142 uint16_t *ver; 2143 2144 ver = (uint16_t *) regid->id_suffix; 2145 *ver = ump->logvol_info->min_udf_readver; 2146 2147 regid->id_suffix[2] = 4; /* unix */ 2148 regid->id_suffix[3] = 8; /* NetBSD */ 2149 } 2150 2151 2152 void 2153 udf_add_impl_regid(struct udf_mount *ump, struct regid *regid) 2154 { 2155 regid->id_suffix[0] = 4; /* unix */ 2156 regid->id_suffix[1] = 8; /* NetBSD */ 2157 } 2158 2159 2160 void 2161 udf_add_app_regid(struct udf_mount *ump, struct regid *regid) 2162 { 2163 regid->id_suffix[0] = APP_VERSION_MAIN; 2164 regid->id_suffix[1] = APP_VERSION_SUB; 2165 } 2166 2167 static int 2168 udf_create_parentfid(struct udf_mount *ump, struct fileid_desc *fid, 2169 struct long_ad *parent, uint64_t unique_id) 2170 { 2171 /* the size of an empty FID is 38 but needs to be a multiple of 4 */ 2172 int fidsize = 40; 2173 2174 udf_inittag(ump, &fid->tag, TAGID_FID, udf_rw32(parent->loc.lb_num)); 2175 fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */ 2176 fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR; 2177 fid->icb = *parent; 2178 fid->icb.longad_uniqueid = udf_rw32((uint32_t) unique_id); 2179 fid->tag.desc_crc_len = fidsize - UDF_DESC_TAG_LENGTH; 2180 (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid); 2181 2182 return fidsize; 2183 } 2184 2185 /* --------------------------------------------------------------------- */ 2186 2187 /* 2188 * Extended attribute support. UDF knows of 3 places for extended attributes: 2189 * 2190 * (a) inside the file's (e)fe in the length of the extended attribute area 2191 * before the allocation descriptors/filedata 2192 * 2193 * (b) in a file referenced by (e)fe->ext_attr_icb and 2194 * 2195 * (c) in the e(fe)'s associated stream directory that can hold various 2196 * sub-files. In the stream directory a few fixed named subfiles are reserved 2197 * for NT/Unix ACL's and OS/2 attributes. 2198 * 2199 * NOTE: Extended attributes are read randomly but allways written 2200 * *atomicaly*. For ACL's this interface is propably different but not known 2201 * to me yet. 2202 * 2203 * Order of extended attributes in a space : 2204 * ECMA 167 EAs 2205 * Non block aligned Implementation Use EAs 2206 * Block aligned Implementation Use EAs 2207 * Application Use EAs 2208 */ 2209 2210 static int 2211 udf_impl_extattr_check(struct impl_extattr_entry *implext) 2212 { 2213 uint16_t *spos; 2214 2215 if (strncmp(implext->imp_id.id, "*UDF", 4) == 0) { 2216 /* checksum valid? */ 2217 DPRINTF(EXTATTR, ("checking UDF impl. attr checksum\n")); 2218 spos = (uint16_t *) implext->data; 2219 if (udf_rw16(*spos) != udf_ea_cksum((uint8_t *) implext)) 2220 return EINVAL; 2221 } 2222 return 0; 2223 } 2224 2225 static void 2226 udf_calc_impl_extattr_checksum(struct impl_extattr_entry *implext) 2227 { 2228 uint16_t *spos; 2229 2230 if (strncmp(implext->imp_id.id, "*UDF", 4) == 0) { 2231 /* set checksum */ 2232 spos = (uint16_t *) implext->data; 2233 *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext)); 2234 } 2235 } 2236 2237 2238 int 2239 udf_extattr_search_intern(struct udf_node *node, 2240 uint32_t sattr, char const *sattrname, 2241 uint32_t *offsetp, uint32_t *lengthp) 2242 { 2243 struct extattrhdr_desc *eahdr; 2244 struct extattr_entry *attrhdr; 2245 struct impl_extattr_entry *implext; 2246 uint32_t offset, a_l, sector_size; 2247 int32_t l_ea; 2248 uint8_t *pos; 2249 int error; 2250 2251 /* get mountpoint */ 2252 sector_size = node->ump->discinfo.sector_size; 2253 2254 /* get information from fe/efe */ 2255 if (node->fe) { 2256 l_ea = udf_rw32(node->fe->l_ea); 2257 eahdr = (struct extattrhdr_desc *) node->fe->data; 2258 } else { 2259 assert(node->efe); 2260 l_ea = udf_rw32(node->efe->l_ea); 2261 eahdr = (struct extattrhdr_desc *) node->efe->data; 2262 } 2263 2264 /* something recorded here? */ 2265 if (l_ea == 0) 2266 return ENOENT; 2267 2268 /* check extended attribute tag; what to do if it fails? */ 2269 error = udf_check_tag(eahdr); 2270 if (error) 2271 return EINVAL; 2272 if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR) 2273 return EINVAL; 2274 error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc)); 2275 if (error) 2276 return EINVAL; 2277 2278 DPRINTF(EXTATTR, ("Found %d bytes of extended attributes\n", l_ea)); 2279 2280 /* looking for Ecma-167 attributes? */ 2281 offset = sizeof(struct extattrhdr_desc); 2282 2283 /* looking for either implemenation use or application use */ 2284 if (sattr == 2048) { /* [4/48.10.8] */ 2285 offset = udf_rw32(eahdr->impl_attr_loc); 2286 if (offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT) 2287 return ENOENT; 2288 } 2289 if (sattr == 65536) { /* [4/48.10.9] */ 2290 offset = udf_rw32(eahdr->appl_attr_loc); 2291 if (offset == UDF_APPL_ATTR_LOC_NOT_PRESENT) 2292 return ENOENT; 2293 } 2294 2295 /* paranoia check offset and l_ea */ 2296 if (l_ea + offset >= sector_size - sizeof(struct extattr_entry)) 2297 return EINVAL; 2298 2299 DPRINTF(EXTATTR, ("Starting at offset %d\n", offset)); 2300 2301 /* find our extended attribute */ 2302 l_ea -= offset; 2303 pos = (uint8_t *) eahdr + offset; 2304 2305 while (l_ea >= sizeof(struct extattr_entry)) { 2306 DPRINTF(EXTATTR, ("%d extended attr bytes left\n", l_ea)); 2307 attrhdr = (struct extattr_entry *) pos; 2308 implext = (struct impl_extattr_entry *) pos; 2309 2310 /* get complete attribute length and check for roque values */ 2311 a_l = udf_rw32(attrhdr->a_l); 2312 DPRINTF(EXTATTR, ("attribute %d:%d, len %d/%d\n", 2313 udf_rw32(attrhdr->type), 2314 attrhdr->subtype, a_l, l_ea)); 2315 if ((a_l == 0) || (a_l > l_ea)) 2316 return EINVAL; 2317 2318 if (attrhdr->type != sattr) 2319 goto next_attribute; 2320 2321 /* we might have found it! */ 2322 if (attrhdr->type < 2048) { /* Ecma-167 attribute */ 2323 *offsetp = offset; 2324 *lengthp = a_l; 2325 return 0; /* success */ 2326 } 2327 2328 /* 2329 * Implementation use and application use extended attributes 2330 * have a name to identify. They share the same structure only 2331 * UDF implementation use extended attributes have a checksum 2332 * we need to check 2333 */ 2334 2335 DPRINTF(EXTATTR, ("named attribute %s\n", implext->imp_id.id)); 2336 if (strcmp(implext->imp_id.id, sattrname) == 0) { 2337 /* we have found our appl/implementation attribute */ 2338 *offsetp = offset; 2339 *lengthp = a_l; 2340 return 0; /* success */ 2341 } 2342 2343 next_attribute: 2344 /* next attribute */ 2345 pos += a_l; 2346 l_ea -= a_l; 2347 offset += a_l; 2348 } 2349 /* not found */ 2350 return ENOENT; 2351 } 2352 2353 2354 static void 2355 udf_extattr_insert_internal(struct udf_mount *ump, union dscrptr *dscr, 2356 struct extattr_entry *extattr) 2357 { 2358 struct file_entry *fe; 2359 struct extfile_entry *efe; 2360 struct extattrhdr_desc *extattrhdr; 2361 struct impl_extattr_entry *implext; 2362 uint32_t impl_attr_loc, appl_attr_loc, l_ea, a_l, exthdr_len; 2363 uint32_t *l_eap, l_ad; 2364 uint16_t *spos; 2365 uint8_t *bpos, *data; 2366 2367 if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { 2368 fe = &dscr->fe; 2369 data = fe->data; 2370 l_eap = &fe->l_ea; 2371 l_ad = udf_rw32(fe->l_ad); 2372 } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { 2373 efe = &dscr->efe; 2374 data = efe->data; 2375 l_eap = &efe->l_ea; 2376 l_ad = udf_rw32(efe->l_ad); 2377 } else { 2378 panic("Bad tag passed to udf_extattr_insert_internal"); 2379 } 2380 2381 /* can't append already written to file descriptors yet */ 2382 assert(l_ad == 0); 2383 2384 /* should have a header! */ 2385 extattrhdr = (struct extattrhdr_desc *) data; 2386 l_ea = udf_rw32(*l_eap); 2387 if (l_ea == 0) { 2388 /* create empty extended attribute header */ 2389 exthdr_len = sizeof(struct extattrhdr_desc); 2390 2391 udf_inittag(ump, &extattrhdr->tag, TAGID_EXTATTR_HDR, 2392 /* loc */ 0); 2393 extattrhdr->impl_attr_loc = udf_rw32(exthdr_len); 2394 extattrhdr->appl_attr_loc = udf_rw32(exthdr_len); 2395 extattrhdr->tag.desc_crc_len = udf_rw16(8); 2396 2397 /* record extended attribute header length */ 2398 l_ea = exthdr_len; 2399 *l_eap = udf_rw32(l_ea); 2400 } 2401 2402 /* extract locations */ 2403 impl_attr_loc = udf_rw32(extattrhdr->impl_attr_loc); 2404 appl_attr_loc = udf_rw32(extattrhdr->appl_attr_loc); 2405 if (impl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT) 2406 impl_attr_loc = l_ea; 2407 if (appl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT) 2408 appl_attr_loc = l_ea; 2409 2410 /* Ecma 167 EAs */ 2411 if (udf_rw32(extattr->type) < 2048) { 2412 assert(impl_attr_loc == l_ea); 2413 assert(appl_attr_loc == l_ea); 2414 } 2415 2416 /* implementation use extended attributes */ 2417 if (udf_rw32(extattr->type) == 2048) { 2418 assert(appl_attr_loc == l_ea); 2419 2420 /* calculate and write extended attribute header checksum */ 2421 implext = (struct impl_extattr_entry *) extattr; 2422 assert(udf_rw32(implext->iu_l) == 4); /* [UDF 3.3.4.5] */ 2423 spos = (uint16_t *) implext->data; 2424 *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext)); 2425 } 2426 2427 /* application use extended attributes */ 2428 assert(udf_rw32(extattr->type) != 65536); 2429 assert(appl_attr_loc == l_ea); 2430 2431 /* append the attribute at the end of the current space */ 2432 bpos = data + udf_rw32(*l_eap); 2433 a_l = udf_rw32(extattr->a_l); 2434 2435 /* update impl. attribute locations */ 2436 if (udf_rw32(extattr->type) < 2048) { 2437 impl_attr_loc = l_ea + a_l; 2438 appl_attr_loc = l_ea + a_l; 2439 } 2440 if (udf_rw32(extattr->type) == 2048) { 2441 appl_attr_loc = l_ea + a_l; 2442 } 2443 2444 /* copy and advance */ 2445 memcpy(bpos, extattr, a_l); 2446 l_ea += a_l; 2447 *l_eap = udf_rw32(l_ea); 2448 2449 /* do the `dance` again backwards */ 2450 if (udf_rw16(ump->logical_vol->tag.descriptor_ver) != 2) { 2451 if (impl_attr_loc == l_ea) 2452 impl_attr_loc = UDF_IMPL_ATTR_LOC_NOT_PRESENT; 2453 if (appl_attr_loc == l_ea) 2454 appl_attr_loc = UDF_APPL_ATTR_LOC_NOT_PRESENT; 2455 } 2456 2457 /* store offsets */ 2458 extattrhdr->impl_attr_loc = udf_rw32(impl_attr_loc); 2459 extattrhdr->appl_attr_loc = udf_rw32(appl_attr_loc); 2460 } 2461 2462 2463 /* --------------------------------------------------------------------- */ 2464 2465 static int 2466 udf_update_lvid_from_vat_extattr(struct udf_node *vat_node) 2467 { 2468 struct udf_mount *ump; 2469 struct udf_logvol_info *lvinfo; 2470 struct impl_extattr_entry *implext; 2471 struct vatlvext_extattr_entry lvext; 2472 const char *extstr = "*UDF VAT LVExtension"; 2473 uint64_t vat_uniqueid; 2474 uint32_t offset, a_l; 2475 uint8_t *ea_start, *lvextpos; 2476 int error; 2477 2478 /* get mountpoint and lvinfo */ 2479 ump = vat_node->ump; 2480 lvinfo = ump->logvol_info; 2481 2482 /* get information from fe/efe */ 2483 if (vat_node->fe) { 2484 vat_uniqueid = udf_rw64(vat_node->fe->unique_id); 2485 ea_start = vat_node->fe->data; 2486 } else { 2487 vat_uniqueid = udf_rw64(vat_node->efe->unique_id); 2488 ea_start = vat_node->efe->data; 2489 } 2490 2491 error = udf_extattr_search_intern(vat_node, 2048, extstr, &offset, &a_l); 2492 if (error) 2493 return error; 2494 2495 implext = (struct impl_extattr_entry *) (ea_start + offset); 2496 error = udf_impl_extattr_check(implext); 2497 if (error) 2498 return error; 2499 2500 /* paranoia */ 2501 if (a_l != sizeof(*implext) -1 + udf_rw32(implext->iu_l) + sizeof(lvext)) { 2502 DPRINTF(VOLUMES, ("VAT LVExtension size doesn't compute\n")); 2503 return EINVAL; 2504 } 2505 2506 /* 2507 * we have found our "VAT LVExtension attribute. BUT due to a 2508 * bug in the specification it might not be word aligned so 2509 * copy first to avoid panics on some machines (!!) 2510 */ 2511 DPRINTF(VOLUMES, ("Found VAT LVExtension attr\n")); 2512 lvextpos = implext->data + udf_rw32(implext->iu_l); 2513 memcpy(&lvext, lvextpos, sizeof(lvext)); 2514 2515 /* check if it was updated the last time */ 2516 if (udf_rw64(lvext.unique_id_chk) == vat_uniqueid) { 2517 lvinfo->num_files = lvext.num_files; 2518 lvinfo->num_directories = lvext.num_directories; 2519 udf_update_logvolname(ump, lvext.logvol_id); 2520 } else { 2521 DPRINTF(VOLUMES, ("VAT LVExtension out of date\n")); 2522 /* replace VAT LVExt by free space EA */ 2523 memset(implext->imp_id.id, 0, UDF_REGID_ID_SIZE); 2524 strcpy(implext->imp_id.id, "*UDF FreeEASpace"); 2525 udf_calc_impl_extattr_checksum(implext); 2526 } 2527 2528 return 0; 2529 } 2530 2531 2532 static int 2533 udf_update_vat_extattr_from_lvid(struct udf_node *vat_node) 2534 { 2535 struct udf_mount *ump; 2536 struct udf_logvol_info *lvinfo; 2537 struct impl_extattr_entry *implext; 2538 struct vatlvext_extattr_entry lvext; 2539 const char *extstr = "*UDF VAT LVExtension"; 2540 uint64_t vat_uniqueid; 2541 uint32_t offset, a_l; 2542 uint8_t *ea_start, *lvextpos; 2543 int error; 2544 2545 /* get mountpoint and lvinfo */ 2546 ump = vat_node->ump; 2547 lvinfo = ump->logvol_info; 2548 2549 /* get information from fe/efe */ 2550 if (vat_node->fe) { 2551 vat_uniqueid = udf_rw64(vat_node->fe->unique_id); 2552 ea_start = vat_node->fe->data; 2553 } else { 2554 vat_uniqueid = udf_rw64(vat_node->efe->unique_id); 2555 ea_start = vat_node->efe->data; 2556 } 2557 2558 error = udf_extattr_search_intern(vat_node, 2048, extstr, &offset, &a_l); 2559 if (error) 2560 return error; 2561 /* found, it existed */ 2562 2563 /* paranoia */ 2564 implext = (struct impl_extattr_entry *) (ea_start + offset); 2565 error = udf_impl_extattr_check(implext); 2566 if (error) { 2567 DPRINTF(VOLUMES, ("VAT LVExtension bad on update\n")); 2568 return error; 2569 } 2570 /* it is correct */ 2571 2572 /* 2573 * we have found our "VAT LVExtension attribute. BUT due to a 2574 * bug in the specification it might not be word aligned so 2575 * copy first to avoid panics on some machines (!!) 2576 */ 2577 DPRINTF(VOLUMES, ("Updating VAT LVExtension attr\n")); 2578 lvextpos = implext->data + udf_rw32(implext->iu_l); 2579 2580 lvext.unique_id_chk = vat_uniqueid; 2581 lvext.num_files = lvinfo->num_files; 2582 lvext.num_directories = lvinfo->num_directories; 2583 memmove(lvext.logvol_id, ump->logical_vol->logvol_id, 128); 2584 2585 memcpy(lvextpos, &lvext, sizeof(lvext)); 2586 2587 return 0; 2588 } 2589 2590 /* --------------------------------------------------------------------- */ 2591 2592 int 2593 udf_vat_read(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset) 2594 { 2595 struct udf_mount *ump = vat_node->ump; 2596 2597 if (offset + size > ump->vat_offset + ump->vat_entries * 4) 2598 return EINVAL; 2599 2600 memcpy(blob, ump->vat_table + offset, size); 2601 return 0; 2602 } 2603 2604 int 2605 udf_vat_write(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset) 2606 { 2607 struct udf_mount *ump = vat_node->ump; 2608 uint32_t offset_high; 2609 uint8_t *new_vat_table; 2610 2611 /* extent VAT allocation if needed */ 2612 offset_high = offset + size; 2613 if (offset_high >= ump->vat_table_alloc_len) { 2614 /* realloc */ 2615 new_vat_table = realloc(ump->vat_table, 2616 ump->vat_table_alloc_len + UDF_VAT_CHUNKSIZE, 2617 M_UDFVOLD, M_WAITOK | M_CANFAIL); 2618 if (!new_vat_table) { 2619 printf("udf_vat_write: can't extent VAT, out of mem\n"); 2620 return ENOMEM; 2621 } 2622 ump->vat_table = new_vat_table; 2623 ump->vat_table_alloc_len += UDF_VAT_CHUNKSIZE; 2624 } 2625 ump->vat_table_len = MAX(ump->vat_table_len, offset_high); 2626 2627 memcpy(ump->vat_table + offset, blob, size); 2628 return 0; 2629 } 2630 2631 /* --------------------------------------------------------------------- */ 2632 2633 /* TODO support previous VAT location writeout */ 2634 static int 2635 udf_update_vat_descriptor(struct udf_mount *ump) 2636 { 2637 struct udf_node *vat_node = ump->vat_node; 2638 struct udf_logvol_info *lvinfo = ump->logvol_info; 2639 struct icb_tag *icbtag; 2640 struct udf_oldvat_tail *oldvat_tl; 2641 struct udf_vat *vat; 2642 uint64_t unique_id; 2643 uint32_t lb_size; 2644 uint8_t *raw_vat; 2645 int filetype, error; 2646 2647 KASSERT(vat_node); 2648 KASSERT(lvinfo); 2649 lb_size = udf_rw32(ump->logical_vol->lb_size); 2650 2651 /* get our new unique_id */ 2652 unique_id = udf_advance_uniqueid(ump); 2653 2654 /* get information from fe/efe */ 2655 if (vat_node->fe) { 2656 icbtag = &vat_node->fe->icbtag; 2657 vat_node->fe->unique_id = udf_rw64(unique_id); 2658 } else { 2659 icbtag = &vat_node->efe->icbtag; 2660 vat_node->efe->unique_id = udf_rw64(unique_id); 2661 } 2662 2663 /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */ 2664 filetype = icbtag->file_type; 2665 KASSERT((filetype == 0) || (filetype == UDF_ICB_FILETYPE_VAT)); 2666 2667 /* allocate piece to process head or tail of VAT file */ 2668 raw_vat = malloc(lb_size, M_TEMP, M_WAITOK); 2669 2670 if (filetype == 0) { 2671 /* 2672 * Update "*UDF VAT LVExtension" extended attribute from the 2673 * lvint if present. 2674 */ 2675 udf_update_vat_extattr_from_lvid(vat_node); 2676 2677 /* setup identifying regid */ 2678 oldvat_tl = (struct udf_oldvat_tail *) raw_vat; 2679 memset(oldvat_tl, 0, sizeof(struct udf_oldvat_tail)); 2680 2681 udf_set_regid(&oldvat_tl->id, "*UDF Virtual Alloc Tbl"); 2682 udf_add_udf_regid(ump, &oldvat_tl->id); 2683 oldvat_tl->prev_vat = udf_rw32(0xffffffff); 2684 2685 /* write out new tail of virtual allocation table file */ 2686 error = udf_vat_write(vat_node, raw_vat, 2687 sizeof(struct udf_oldvat_tail), ump->vat_entries * 4); 2688 } else { 2689 /* compose the VAT2 header */ 2690 vat = (struct udf_vat *) raw_vat; 2691 memset(vat, 0, sizeof(struct udf_vat)); 2692 2693 vat->header_len = udf_rw16(152); /* as per spec */ 2694 vat->impl_use_len = udf_rw16(0); 2695 memmove(vat->logvol_id, ump->logical_vol->logvol_id, 128); 2696 vat->prev_vat = udf_rw32(0xffffffff); 2697 vat->num_files = lvinfo->num_files; 2698 vat->num_directories = lvinfo->num_directories; 2699 vat->min_udf_readver = lvinfo->min_udf_readver; 2700 vat->min_udf_writever = lvinfo->min_udf_writever; 2701 vat->max_udf_writever = lvinfo->max_udf_writever; 2702 2703 error = udf_vat_write(vat_node, raw_vat, 2704 sizeof(struct udf_vat), 0); 2705 } 2706 free(raw_vat, M_TEMP); 2707 2708 return error; /* success! */ 2709 } 2710 2711 2712 int 2713 udf_writeout_vat(struct udf_mount *ump) 2714 { 2715 struct udf_node *vat_node = ump->vat_node; 2716 uint32_t vat_length; 2717 int error; 2718 2719 KASSERT(vat_node); 2720 2721 DPRINTF(CALL, ("udf_writeout_vat\n")); 2722 2723 mutex_enter(&ump->allocate_mutex); 2724 udf_update_vat_descriptor(ump); 2725 2726 /* write out the VAT contents ; TODO intelligent writing */ 2727 vat_length = ump->vat_table_len; 2728 error = vn_rdwr(UIO_WRITE, vat_node->vnode, 2729 ump->vat_table, ump->vat_table_len, 0, 2730 UIO_SYSSPACE, IO_NODELOCKED, FSCRED, NULL, NULL); 2731 if (error) { 2732 printf("udf_writeout_vat: failed to write out VAT contents\n"); 2733 goto out; 2734 } 2735 2736 mutex_exit(&ump->allocate_mutex); 2737 2738 vflushbuf(ump->vat_node->vnode, 1 /* sync */); 2739 error = VOP_FSYNC(ump->vat_node->vnode, 2740 FSCRED, FSYNC_WAIT, 0, 0); 2741 if (error) 2742 printf("udf_writeout_vat: error writing VAT node!\n"); 2743 out: 2744 2745 return error; 2746 } 2747 2748 /* --------------------------------------------------------------------- */ 2749 2750 /* 2751 * Read in relevant pieces of VAT file and check if its indeed a VAT file 2752 * descriptor. If OK, read in complete VAT file. 2753 */ 2754 2755 static int 2756 udf_check_for_vat(struct udf_node *vat_node) 2757 { 2758 struct udf_mount *ump; 2759 struct icb_tag *icbtag; 2760 struct timestamp *mtime; 2761 struct udf_vat *vat; 2762 struct udf_oldvat_tail *oldvat_tl; 2763 struct udf_logvol_info *lvinfo; 2764 uint64_t unique_id; 2765 uint32_t vat_length; 2766 uint32_t vat_offset, vat_entries, vat_table_alloc_len; 2767 uint32_t sector_size; 2768 uint32_t *raw_vat; 2769 uint8_t *vat_table; 2770 char *regid_name; 2771 int filetype; 2772 int error; 2773 2774 /* vat_length is really 64 bits though impossible */ 2775 2776 DPRINTF(VOLUMES, ("Checking for VAT\n")); 2777 if (!vat_node) 2778 return ENOENT; 2779 2780 /* get mount info */ 2781 ump = vat_node->ump; 2782 sector_size = udf_rw32(ump->logical_vol->lb_size); 2783 2784 /* check assertions */ 2785 assert(vat_node->fe || vat_node->efe); 2786 assert(ump->logvol_integrity); 2787 2788 /* set vnode type to regular file or we can't read from it! */ 2789 vat_node->vnode->v_type = VREG; 2790 2791 /* get information from fe/efe */ 2792 if (vat_node->fe) { 2793 vat_length = udf_rw64(vat_node->fe->inf_len); 2794 icbtag = &vat_node->fe->icbtag; 2795 mtime = &vat_node->fe->mtime; 2796 unique_id = udf_rw64(vat_node->fe->unique_id); 2797 } else { 2798 vat_length = udf_rw64(vat_node->efe->inf_len); 2799 icbtag = &vat_node->efe->icbtag; 2800 mtime = &vat_node->efe->mtime; 2801 unique_id = udf_rw64(vat_node->efe->unique_id); 2802 } 2803 2804 /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */ 2805 filetype = icbtag->file_type; 2806 if ((filetype != 0) && (filetype != UDF_ICB_FILETYPE_VAT)) 2807 return ENOENT; 2808 2809 DPRINTF(VOLUMES, ("\tPossible VAT length %d\n", vat_length)); 2810 2811 vat_table_alloc_len = 2812 ((vat_length + UDF_VAT_CHUNKSIZE-1) / UDF_VAT_CHUNKSIZE) 2813 * UDF_VAT_CHUNKSIZE; 2814 2815 vat_table = malloc(vat_table_alloc_len, M_UDFVOLD, 2816 M_CANFAIL | M_WAITOK); 2817 if (vat_table == NULL) { 2818 printf("allocation of %d bytes failed for VAT\n", 2819 vat_table_alloc_len); 2820 return ENOMEM; 2821 } 2822 2823 /* allocate piece to read in head or tail of VAT file */ 2824 raw_vat = malloc(sector_size, M_TEMP, M_WAITOK); 2825 2826 /* 2827 * check contents of the file if its the old 1.50 VAT table format. 2828 * Its notoriously broken and allthough some implementations support an 2829 * extention as defined in the UDF 1.50 errata document, its doubtfull 2830 * to be useable since a lot of implementations don't maintain it. 2831 */ 2832 lvinfo = ump->logvol_info; 2833 2834 if (filetype == 0) { 2835 /* definition */ 2836 vat_offset = 0; 2837 vat_entries = (vat_length-36)/4; 2838 2839 /* read in tail of virtual allocation table file */ 2840 error = vn_rdwr(UIO_READ, vat_node->vnode, 2841 (uint8_t *) raw_vat, 2842 sizeof(struct udf_oldvat_tail), 2843 vat_entries * 4, 2844 UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED, 2845 NULL, NULL); 2846 if (error) 2847 goto out; 2848 2849 /* check 1.50 VAT */ 2850 oldvat_tl = (struct udf_oldvat_tail *) raw_vat; 2851 regid_name = (char *) oldvat_tl->id.id; 2852 error = strncmp(regid_name, "*UDF Virtual Alloc Tbl", 22); 2853 if (error) { 2854 DPRINTF(VOLUMES, ("VAT format 1.50 rejected\n")); 2855 error = ENOENT; 2856 goto out; 2857 } 2858 2859 /* 2860 * update LVID from "*UDF VAT LVExtension" extended attribute 2861 * if present. 2862 */ 2863 udf_update_lvid_from_vat_extattr(vat_node); 2864 } else { 2865 /* read in head of virtual allocation table file */ 2866 error = vn_rdwr(UIO_READ, vat_node->vnode, 2867 (uint8_t *) raw_vat, 2868 sizeof(struct udf_vat), 0, 2869 UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED, 2870 NULL, NULL); 2871 if (error) 2872 goto out; 2873 2874 /* definition */ 2875 vat = (struct udf_vat *) raw_vat; 2876 vat_offset = vat->header_len; 2877 vat_entries = (vat_length - vat_offset)/4; 2878 2879 assert(lvinfo); 2880 lvinfo->num_files = vat->num_files; 2881 lvinfo->num_directories = vat->num_directories; 2882 lvinfo->min_udf_readver = vat->min_udf_readver; 2883 lvinfo->min_udf_writever = vat->min_udf_writever; 2884 lvinfo->max_udf_writever = vat->max_udf_writever; 2885 2886 udf_update_logvolname(ump, vat->logvol_id); 2887 } 2888 2889 /* read in complete VAT file */ 2890 error = vn_rdwr(UIO_READ, vat_node->vnode, 2891 vat_table, 2892 vat_length, 0, 2893 UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED, FSCRED, 2894 NULL, NULL); 2895 if (error) 2896 printf("read in of complete VAT file failed (error %d)\n", 2897 error); 2898 if (error) 2899 goto out; 2900 2901 DPRINTF(VOLUMES, ("VAT format accepted, marking it closed\n")); 2902 ump->logvol_integrity->lvint_next_unique_id = unique_id; 2903 ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED); 2904 ump->logvol_integrity->time = *mtime; 2905 2906 ump->vat_table_len = vat_length; 2907 ump->vat_table_alloc_len = vat_table_alloc_len; 2908 ump->vat_table = vat_table; 2909 ump->vat_offset = vat_offset; 2910 ump->vat_entries = vat_entries; 2911 ump->vat_last_free_lb = 0; /* start at beginning */ 2912 2913 out: 2914 if (error) { 2915 if (vat_table) 2916 free(vat_table, M_UDFVOLD); 2917 } 2918 free(raw_vat, M_TEMP); 2919 2920 return error; 2921 } 2922 2923 /* --------------------------------------------------------------------- */ 2924 2925 static int 2926 udf_search_vat(struct udf_mount *ump, union udf_pmap *mapping) 2927 { 2928 struct udf_node *vat_node; 2929 struct long_ad icb_loc; 2930 uint32_t early_vat_loc, late_vat_loc, vat_loc; 2931 int error; 2932 2933 /* mapping info not needed */ 2934 mapping = mapping; 2935 2936 vat_loc = ump->last_possible_vat_location; 2937 early_vat_loc = vat_loc - 256; /* 8 blocks of 32 sectors */ 2938 2939 DPRINTF(VOLUMES, ("1) last possible %d, early_vat_loc %d \n", 2940 vat_loc, early_vat_loc)); 2941 early_vat_loc = MAX(early_vat_loc, ump->first_possible_vat_location); 2942 late_vat_loc = vat_loc + 1024; 2943 2944 DPRINTF(VOLUMES, ("2) last possible %d, early_vat_loc %d \n", 2945 vat_loc, early_vat_loc)); 2946 2947 /* start looking from the end of the range */ 2948 do { 2949 DPRINTF(VOLUMES, ("Checking for VAT at sector %d\n", vat_loc)); 2950 icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART); 2951 icb_loc.loc.lb_num = udf_rw32(vat_loc); 2952 2953 error = udf_get_node(ump, &icb_loc, &vat_node); 2954 if (!error) { 2955 error = udf_check_for_vat(vat_node); 2956 DPRINTFIF(VOLUMES, !error, 2957 ("VAT accepted at %d\n", vat_loc)); 2958 if (!error) 2959 break; 2960 } 2961 if (vat_node) { 2962 vput(vat_node->vnode); 2963 vat_node = NULL; 2964 } 2965 vat_loc--; /* walk backwards */ 2966 } while (vat_loc >= early_vat_loc); 2967 2968 /* keep our VAT node around */ 2969 if (vat_node) { 2970 UDF_SET_SYSTEMFILE(vat_node->vnode); 2971 ump->vat_node = vat_node; 2972 } 2973 2974 return error; 2975 } 2976 2977 /* --------------------------------------------------------------------- */ 2978 2979 static int 2980 udf_read_sparables(struct udf_mount *ump, union udf_pmap *mapping) 2981 { 2982 union dscrptr *dscr; 2983 struct part_map_spare *pms = &mapping->pms; 2984 uint32_t lb_num; 2985 int spar, error; 2986 2987 /* 2988 * The partition mapping passed on to us specifies the information we 2989 * need to locate and initialise the sparable partition mapping 2990 * information we need. 2991 */ 2992 2993 DPRINTF(VOLUMES, ("Read sparable table\n")); 2994 ump->sparable_packet_size = udf_rw16(pms->packet_len); 2995 KASSERT(ump->sparable_packet_size >= ump->packet_size); /* XXX */ 2996 2997 for (spar = 0; spar < pms->n_st; spar++) { 2998 lb_num = pms->st_loc[spar]; 2999 DPRINTF(VOLUMES, ("Checking for sparing table %d\n", lb_num)); 3000 error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr); 3001 if (!error && dscr) { 3002 if (udf_rw16(dscr->tag.id) == TAGID_SPARING_TABLE) { 3003 if (ump->sparing_table) 3004 free(ump->sparing_table, M_UDFVOLD); 3005 ump->sparing_table = &dscr->spt; 3006 dscr = NULL; 3007 DPRINTF(VOLUMES, 3008 ("Sparing table accepted (%d entries)\n", 3009 udf_rw16(ump->sparing_table->rt_l))); 3010 break; /* we're done */ 3011 } 3012 } 3013 if (dscr) 3014 free(dscr, M_UDFVOLD); 3015 } 3016 3017 if (ump->sparing_table) 3018 return 0; 3019 3020 return ENOENT; 3021 } 3022 3023 /* --------------------------------------------------------------------- */ 3024 3025 static int 3026 udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping) 3027 { 3028 struct part_map_meta *pmm = &mapping->pmm; 3029 struct long_ad icb_loc; 3030 struct vnode *vp; 3031 int error; 3032 3033 DPRINTF(VOLUMES, ("Reading in Metadata files\n")); 3034 icb_loc.loc.part_num = pmm->part_num; 3035 icb_loc.loc.lb_num = pmm->meta_file_lbn; 3036 DPRINTF(VOLUMES, ("Metadata file\n")); 3037 error = udf_get_node(ump, &icb_loc, &ump->metadata_node); 3038 if (ump->metadata_node) { 3039 vp = ump->metadata_node->vnode; 3040 UDF_SET_SYSTEMFILE(vp); 3041 } 3042 3043 icb_loc.loc.lb_num = pmm->meta_mirror_file_lbn; 3044 if (icb_loc.loc.lb_num != -1) { 3045 DPRINTF(VOLUMES, ("Metadata copy file\n")); 3046 error = udf_get_node(ump, &icb_loc, &ump->metadatamirror_node); 3047 if (ump->metadatamirror_node) { 3048 vp = ump->metadatamirror_node->vnode; 3049 UDF_SET_SYSTEMFILE(vp); 3050 } 3051 } 3052 3053 icb_loc.loc.lb_num = pmm->meta_bitmap_file_lbn; 3054 if (icb_loc.loc.lb_num != -1) { 3055 DPRINTF(VOLUMES, ("Metadata bitmap file\n")); 3056 error = udf_get_node(ump, &icb_loc, &ump->metadatabitmap_node); 3057 if (ump->metadatabitmap_node) { 3058 vp = ump->metadatabitmap_node->vnode; 3059 UDF_SET_SYSTEMFILE(vp); 3060 } 3061 } 3062 3063 /* if we're mounting read-only we relax the requirements */ 3064 if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) { 3065 error = EFAULT; 3066 if (ump->metadata_node) 3067 error = 0; 3068 if ((ump->metadata_node == NULL) && (ump->metadatamirror_node)) { 3069 printf( "udf mount: Metadata file not readable, " 3070 "substituting Metadata copy file\n"); 3071 ump->metadata_node = ump->metadatamirror_node; 3072 ump->metadatamirror_node = NULL; 3073 error = 0; 3074 } 3075 } else { 3076 /* mounting read/write */ 3077 /* XXX DISABLED! metadata writing is not working yet XXX */ 3078 if (error) 3079 error = EROFS; 3080 } 3081 DPRINTFIF(VOLUMES, error, ("udf mount: failed to read " 3082 "metadata files\n")); 3083 return error; 3084 } 3085 3086 /* --------------------------------------------------------------------- */ 3087 3088 int 3089 udf_read_vds_tables(struct udf_mount *ump) 3090 { 3091 union udf_pmap *mapping; 3092 /* struct udf_args *args = &ump->mount_args; */ 3093 uint32_t n_pm, mt_l; 3094 uint32_t log_part; 3095 uint8_t *pmap_pos; 3096 int pmap_size; 3097 int error; 3098 3099 /* Iterate (again) over the part mappings for locations */ 3100 n_pm = udf_rw32(ump->logical_vol->n_pm); /* num partmaps */ 3101 mt_l = udf_rw32(ump->logical_vol->mt_l); /* partmaps data length */ 3102 pmap_pos = ump->logical_vol->maps; 3103 3104 for (log_part = 0; log_part < n_pm; log_part++) { 3105 mapping = (union udf_pmap *) pmap_pos; 3106 switch (ump->vtop_tp[log_part]) { 3107 case UDF_VTOP_TYPE_PHYS : 3108 /* nothing */ 3109 break; 3110 case UDF_VTOP_TYPE_VIRT : 3111 /* search and load VAT */ 3112 error = udf_search_vat(ump, mapping); 3113 if (error) 3114 return ENOENT; 3115 break; 3116 case UDF_VTOP_TYPE_SPARABLE : 3117 /* load one of the sparable tables */ 3118 error = udf_read_sparables(ump, mapping); 3119 if (error) 3120 return ENOENT; 3121 break; 3122 case UDF_VTOP_TYPE_META : 3123 /* load the associated file descriptors */ 3124 error = udf_read_metadata_nodes(ump, mapping); 3125 if (error) 3126 return ENOENT; 3127 break; 3128 default: 3129 break; 3130 } 3131 pmap_size = pmap_pos[1]; 3132 pmap_pos += pmap_size; 3133 } 3134 3135 /* read in and check unallocated and free space info if writing */ 3136 if ((ump->vfs_mountp->mnt_flag & MNT_RDONLY) == 0) { 3137 error = udf_read_physical_partition_spacetables(ump); 3138 if (error) 3139 return error; 3140 3141 /* also read in metadata partion spacebitmap if defined */ 3142 error = udf_read_metadata_partition_spacetable(ump); 3143 return error; 3144 } 3145 3146 return 0; 3147 } 3148 3149 /* --------------------------------------------------------------------- */ 3150 3151 int 3152 udf_read_rootdirs(struct udf_mount *ump) 3153 { 3154 union dscrptr *dscr; 3155 /* struct udf_args *args = &ump->mount_args; */ 3156 struct udf_node *rootdir_node, *streamdir_node; 3157 struct long_ad fsd_loc, *dir_loc; 3158 uint32_t lb_num, dummy; 3159 uint32_t fsd_len; 3160 int dscr_type; 3161 int error; 3162 3163 /* TODO implement FSD reading in separate function like integrity? */ 3164 /* get fileset descriptor sequence */ 3165 fsd_loc = ump->logical_vol->lv_fsd_loc; 3166 fsd_len = udf_rw32(fsd_loc.len); 3167 3168 dscr = NULL; 3169 error = 0; 3170 while (fsd_len || error) { 3171 DPRINTF(VOLUMES, ("fsd_len = %d\n", fsd_len)); 3172 /* translate fsd_loc to lb_num */ 3173 error = udf_translate_vtop(ump, &fsd_loc, &lb_num, &dummy); 3174 if (error) 3175 break; 3176 DPRINTF(VOLUMES, ("Reading FSD at lb %d\n", lb_num)); 3177 error = udf_read_phys_dscr(ump, lb_num, M_UDFVOLD, &dscr); 3178 /* end markers */ 3179 if (error || (dscr == NULL)) 3180 break; 3181 3182 /* analyse */ 3183 dscr_type = udf_rw16(dscr->tag.id); 3184 if (dscr_type == TAGID_TERM) 3185 break; 3186 if (dscr_type != TAGID_FSD) { 3187 free(dscr, M_UDFVOLD); 3188 return ENOENT; 3189 } 3190 3191 /* 3192 * TODO check for multiple fileset descriptors; its only 3193 * picking the last now. Also check for FSD 3194 * correctness/interpretability 3195 */ 3196 3197 /* update */ 3198 if (ump->fileset_desc) { 3199 free(ump->fileset_desc, M_UDFVOLD); 3200 } 3201 ump->fileset_desc = &dscr->fsd; 3202 dscr = NULL; 3203 3204 /* continue to the next fsd */ 3205 fsd_len -= ump->discinfo.sector_size; 3206 fsd_loc.loc.lb_num = udf_rw32(udf_rw32(fsd_loc.loc.lb_num)+1); 3207 3208 /* follow up to fsd->next_ex (long_ad) if its not null */ 3209 if (udf_rw32(ump->fileset_desc->next_ex.len)) { 3210 DPRINTF(VOLUMES, ("follow up FSD extent\n")); 3211 fsd_loc = ump->fileset_desc->next_ex; 3212 fsd_len = udf_rw32(ump->fileset_desc->next_ex.len); 3213 } 3214 } 3215 if (dscr) 3216 free(dscr, M_UDFVOLD); 3217 3218 /* there has to be one */ 3219 if (ump->fileset_desc == NULL) 3220 return ENOENT; 3221 3222 DPRINTF(VOLUMES, ("FSD read in fine\n")); 3223 DPRINTF(VOLUMES, ("Updating fsd logical volume id\n")); 3224 udf_update_logvolname(ump, ump->logical_vol->logvol_id); 3225 3226 /* 3227 * Now the FSD is known, read in the rootdirectory and if one exists, 3228 * the system stream dir. Some files in the system streamdir are not 3229 * wanted in this implementation since they are not maintained. If 3230 * writing is enabled we'll delete these files if they exist. 3231 */ 3232 3233 rootdir_node = streamdir_node = NULL; 3234 dir_loc = NULL; 3235 3236 /* try to read in the rootdir */ 3237 dir_loc = &ump->fileset_desc->rootdir_icb; 3238 error = udf_get_node(ump, dir_loc, &rootdir_node); 3239 if (error) 3240 return ENOENT; 3241 3242 /* aparently it read in fine */ 3243 3244 /* 3245 * Try the system stream directory; not very likely in the ones we 3246 * test, but for completeness. 3247 */ 3248 dir_loc = &ump->fileset_desc->streamdir_icb; 3249 if (udf_rw32(dir_loc->len)) { 3250 printf("udf_read_rootdirs: streamdir defined "); 3251 error = udf_get_node(ump, dir_loc, &streamdir_node); 3252 if (error) { 3253 printf("but error in streamdir reading\n"); 3254 } else { 3255 printf("but ignored\n"); 3256 /* 3257 * TODO process streamdir `baddies' i.e. files we dont 3258 * want if R/W 3259 */ 3260 } 3261 } 3262 3263 DPRINTF(VOLUMES, ("Rootdir(s) read in fine\n")); 3264 3265 /* release the vnodes again; they'll be auto-recycled later */ 3266 if (streamdir_node) { 3267 vput(streamdir_node->vnode); 3268 } 3269 if (rootdir_node) { 3270 vput(rootdir_node->vnode); 3271 } 3272 3273 return 0; 3274 } 3275 3276 /* --------------------------------------------------------------------- */ 3277 3278 /* To make absolutely sure we are NOT returning zero, add one :) */ 3279 3280 long 3281 udf_calchash(struct long_ad *icbptr) 3282 { 3283 /* ought to be enough since each mountpoint has its own chain */ 3284 return udf_rw32(icbptr->loc.lb_num) + 1; 3285 } 3286 3287 3288 static struct udf_node * 3289 udf_hash_lookup(struct udf_mount *ump, struct long_ad *icbptr) 3290 { 3291 struct udf_node *node; 3292 struct vnode *vp; 3293 uint32_t hashline; 3294 3295 loop: 3296 mutex_enter(&ump->ihash_lock); 3297 3298 hashline = udf_calchash(icbptr) & UDF_INODE_HASHMASK; 3299 LIST_FOREACH(node, &ump->udf_nodes[hashline], hashchain) { 3300 assert(node); 3301 if (node->loc.loc.lb_num == icbptr->loc.lb_num && 3302 node->loc.loc.part_num == icbptr->loc.part_num) { 3303 vp = node->vnode; 3304 assert(vp); 3305 mutex_enter(&vp->v_interlock); 3306 mutex_exit(&ump->ihash_lock); 3307 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) 3308 goto loop; 3309 return node; 3310 } 3311 } 3312 mutex_exit(&ump->ihash_lock); 3313 3314 return NULL; 3315 } 3316 3317 3318 static void 3319 udf_sorted_list_insert(struct udf_node *node) 3320 { 3321 struct udf_mount *ump; 3322 struct udf_node *s_node, *last_node; 3323 uint32_t loc, s_loc; 3324 3325 ump = node->ump; 3326 last_node = NULL; /* XXX gcc */ 3327 3328 if (LIST_EMPTY(&ump->sorted_udf_nodes)) { 3329 LIST_INSERT_HEAD(&ump->sorted_udf_nodes, node, sortchain); 3330 return; 3331 } 3332 3333 /* 3334 * We sort on logical block number here and not on physical block 3335 * number here. Ideally we should go for the physical block nr to get 3336 * better sync performance though this sort will ensure that packets 3337 * won't get spit up unnessisarily. 3338 */ 3339 3340 loc = udf_rw32(node->loc.loc.lb_num); 3341 LIST_FOREACH(s_node, &ump->sorted_udf_nodes, sortchain) { 3342 s_loc = udf_rw32(s_node->loc.loc.lb_num); 3343 if (s_loc > loc) { 3344 LIST_INSERT_BEFORE(s_node, node, sortchain); 3345 return; 3346 } 3347 last_node = s_node; 3348 } 3349 LIST_INSERT_AFTER(last_node, node, sortchain); 3350 } 3351 3352 3353 static void 3354 udf_register_node(struct udf_node *node) 3355 { 3356 struct udf_mount *ump; 3357 struct udf_node *chk; 3358 uint32_t hashline; 3359 3360 ump = node->ump; 3361 mutex_enter(&ump->ihash_lock); 3362 3363 /* add to our hash table */ 3364 hashline = udf_calchash(&node->loc) & UDF_INODE_HASHMASK; 3365 #ifdef DEBUG 3366 LIST_FOREACH(chk, &ump->udf_nodes[hashline], hashchain) { 3367 assert(chk); 3368 if (chk->loc.loc.lb_num == node->loc.loc.lb_num && 3369 chk->loc.loc.part_num == node->loc.loc.part_num) 3370 panic("Double node entered\n"); 3371 } 3372 #else 3373 chk = NULL; 3374 #endif 3375 LIST_INSERT_HEAD(&ump->udf_nodes[hashline], node, hashchain); 3376 3377 /* add to our sorted list */ 3378 udf_sorted_list_insert(node); 3379 3380 mutex_exit(&ump->ihash_lock); 3381 } 3382 3383 3384 static void 3385 udf_deregister_node(struct udf_node *node) 3386 { 3387 struct udf_mount *ump; 3388 3389 ump = node->ump; 3390 mutex_enter(&ump->ihash_lock); 3391 3392 /* from hash and sorted list */ 3393 LIST_REMOVE(node, hashchain); 3394 LIST_REMOVE(node, sortchain); 3395 3396 mutex_exit(&ump->ihash_lock); 3397 } 3398 3399 /* --------------------------------------------------------------------- */ 3400 3401 int 3402 udf_open_logvol(struct udf_mount *ump) 3403 { 3404 int logvol_integrity; 3405 int error; 3406 3407 /* already/still open? */ 3408 logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type); 3409 if (logvol_integrity == UDF_INTEGRITY_OPEN) 3410 return 0; 3411 3412 /* can we open it ? */ 3413 if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) 3414 return EROFS; 3415 3416 /* setup write parameters */ 3417 DPRINTF(VOLUMES, ("Setting up write parameters\n")); 3418 if ((error = udf_setup_writeparams(ump)) != 0) 3419 return error; 3420 3421 /* determine data and metadata tracks (most likely same) */ 3422 error = udf_search_writing_tracks(ump); 3423 if (error) { 3424 /* most likely lack of space */ 3425 printf("udf_open_logvol: error searching writing tracks\n"); 3426 return EROFS; 3427 } 3428 3429 /* writeout/update lvint on disc or only in memory */ 3430 DPRINTF(VOLUMES, ("Opening logical volume\n")); 3431 if (ump->lvopen & UDF_OPEN_SESSION) { 3432 /* TODO implement writeout of VRS + VDS */ 3433 printf( "udf_open_logvol:Opening a closed session not yet " 3434 "implemented\n"); 3435 return EROFS; 3436 3437 /* determine data and metadata tracks again */ 3438 error = udf_search_writing_tracks(ump); 3439 } 3440 3441 /* mark it open */ 3442 ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_OPEN); 3443 3444 /* do we need to write it out? */ 3445 if (ump->lvopen & UDF_WRITE_LVINT) { 3446 error = udf_writeout_lvint(ump, ump->lvopen); 3447 /* if we couldn't write it mark it closed again */ 3448 if (error) { 3449 ump->logvol_integrity->integrity_type = 3450 udf_rw32(UDF_INTEGRITY_CLOSED); 3451 return error; 3452 } 3453 } 3454 3455 return 0; 3456 } 3457 3458 3459 int 3460 udf_close_logvol(struct udf_mount *ump, int mntflags) 3461 { 3462 int logvol_integrity; 3463 int error = 0, error1 = 0, error2 = 0; 3464 int n; 3465 3466 /* already/still closed? */ 3467 logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type); 3468 if (logvol_integrity == UDF_INTEGRITY_CLOSED) 3469 return 0; 3470 3471 /* writeout/update lvint or write out VAT */ 3472 DPRINTF(VOLUMES, ("Closing logical volume\n")); 3473 if (ump->lvclose & UDF_WRITE_VAT) { 3474 DPRINTF(VOLUMES, ("lvclose & UDF_WRITE_VAT\n")); 3475 3476 /* write out the VAT node */ 3477 DPRINTF(VOLUMES, ("writeout vat_node\n")); 3478 udf_writeout_vat(ump); 3479 3480 vflushbuf(ump->vat_node->vnode, 1 /* sync */); 3481 for (n = 0; n < 16; n++) { 3482 ump->vat_node->i_flags |= IN_MODIFIED; 3483 error = VOP_FSYNC(ump->vat_node->vnode, 3484 FSCRED, FSYNC_WAIT, 0, 0); 3485 } 3486 if (error) { 3487 printf("udf_close_logvol: writeout of VAT failed\n"); 3488 return error; 3489 } 3490 } 3491 3492 if (ump->lvclose & UDF_WRITE_PART_BITMAPS) { 3493 /* sync writeout metadata spacetable if existing */ 3494 error1 = udf_write_metadata_partition_spacetable(ump, true); 3495 if (error1) 3496 printf( "udf_close_logvol: writeout of metadata space " 3497 "bitmap failed\n"); 3498 3499 /* sync writeout partition spacetables */ 3500 error2 = udf_write_physical_partition_spacetables(ump, true); 3501 if (error2) 3502 printf( "udf_close_logvol: writeout of space tables " 3503 "failed\n"); 3504 3505 if (error1 || error2) 3506 return (error1 | error2); 3507 3508 ump->lvclose &= ~UDF_WRITE_PART_BITMAPS; 3509 } 3510 3511 if (ump->lvclose & UDF_CLOSE_SESSION) { 3512 printf("TODO: Closing a session is not yet implemented\n"); 3513 return EROFS; 3514 ump->lvopen |= UDF_OPEN_SESSION; 3515 } 3516 3517 /* mark it closed */ 3518 ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED); 3519 3520 /* do we need to write out the logical volume integrity */ 3521 if (ump->lvclose & UDF_WRITE_LVINT) 3522 error = udf_writeout_lvint(ump, ump->lvopen); 3523 if (error) { 3524 /* HELP now what? mark it open again for now */ 3525 ump->logvol_integrity->integrity_type = 3526 udf_rw32(UDF_INTEGRITY_OPEN); 3527 return error; 3528 } 3529 3530 (void) udf_synchronise_caches(ump); 3531 3532 return 0; 3533 } 3534 3535 /* --------------------------------------------------------------------- */ 3536 3537 /* 3538 * Genfs interfacing 3539 * 3540 * static const struct genfs_ops udf_genfsops = { 3541 * .gop_size = genfs_size, 3542 * size of transfers 3543 * .gop_alloc = udf_gop_alloc, 3544 * allocate len bytes at offset 3545 * .gop_write = genfs_gop_write, 3546 * putpages interface code 3547 * .gop_markupdate = udf_gop_markupdate, 3548 * set update/modify flags etc. 3549 * } 3550 */ 3551 3552 /* 3553 * Genfs interface. These four functions are the only ones defined though not 3554 * documented... great.... 3555 */ 3556 3557 /* 3558 * Callback from genfs to allocate len bytes at offset off; only called when 3559 * filling up gaps in the allocation. 3560 */ 3561 /* XXX should we check if there is space enough in udf_gop_alloc? */ 3562 static int 3563 udf_gop_alloc(struct vnode *vp, off_t off, 3564 off_t len, int flags, kauth_cred_t cred) 3565 { 3566 #if 0 3567 struct udf_node *udf_node = VTOI(vp); 3568 struct udf_mount *ump = udf_node->ump; 3569 uint32_t lb_size, num_lb; 3570 #endif 3571 3572 DPRINTF(NOTIMPL, ("udf_gop_alloc not implemented\n")); 3573 DPRINTF(ALLOC, ("udf_gop_alloc called for %"PRIu64" bytes\n", len)); 3574 3575 return 0; 3576 } 3577 3578 3579 /* 3580 * callback from genfs to update our flags 3581 */ 3582 static void 3583 udf_gop_markupdate(struct vnode *vp, int flags) 3584 { 3585 struct udf_node *udf_node = VTOI(vp); 3586 u_long mask = 0; 3587 3588 if ((flags & GOP_UPDATE_ACCESSED) != 0) { 3589 mask = IN_ACCESS; 3590 } 3591 if ((flags & GOP_UPDATE_MODIFIED) != 0) { 3592 if (vp->v_type == VREG) { 3593 mask |= IN_CHANGE | IN_UPDATE; 3594 } else { 3595 mask |= IN_MODIFY; 3596 } 3597 } 3598 if (mask) { 3599 udf_node->i_flags |= mask; 3600 } 3601 } 3602 3603 3604 static const struct genfs_ops udf_genfsops = { 3605 .gop_size = genfs_size, 3606 .gop_alloc = udf_gop_alloc, 3607 .gop_write = genfs_gop_write_rwmap, 3608 .gop_markupdate = udf_gop_markupdate, 3609 }; 3610 3611 3612 /* --------------------------------------------------------------------- */ 3613 3614 int 3615 udf_write_terminator(struct udf_mount *ump, uint32_t sector) 3616 { 3617 union dscrptr *dscr; 3618 int error; 3619 3620 dscr = malloc(ump->discinfo.sector_size, M_TEMP, M_WAITOK); 3621 bzero(dscr, ump->discinfo.sector_size); 3622 udf_inittag(ump, &dscr->tag, TAGID_TERM, sector); 3623 3624 /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */ 3625 dscr->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH); 3626 (void) udf_validate_tag_and_crc_sums(dscr); 3627 3628 error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, 3629 dscr, sector, sector); 3630 3631 free(dscr, M_TEMP); 3632 3633 return error; 3634 } 3635 3636 3637 /* --------------------------------------------------------------------- */ 3638 3639 /* UDF<->unix converters */ 3640 3641 /* --------------------------------------------------------------------- */ 3642 3643 static mode_t 3644 udf_perm_to_unix_mode(uint32_t perm) 3645 { 3646 mode_t mode; 3647 3648 mode = ((perm & UDF_FENTRY_PERM_USER_MASK) ); 3649 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK ) >> 2); 3650 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 3651 3652 return mode; 3653 } 3654 3655 /* --------------------------------------------------------------------- */ 3656 3657 static uint32_t 3658 unix_mode_to_udf_perm(mode_t mode) 3659 { 3660 uint32_t perm; 3661 3662 perm = ((mode & S_IRWXO) ); 3663 perm |= ((mode & S_IRWXG) << 2); 3664 perm |= ((mode & S_IRWXU) << 4); 3665 perm |= ((mode & S_IWOTH) << 3); 3666 perm |= ((mode & S_IWGRP) << 5); 3667 perm |= ((mode & S_IWUSR) << 7); 3668 3669 return perm; 3670 } 3671 3672 /* --------------------------------------------------------------------- */ 3673 3674 static uint32_t 3675 udf_icb_to_unix_filetype(uint32_t icbftype) 3676 { 3677 switch (icbftype) { 3678 case UDF_ICB_FILETYPE_DIRECTORY : 3679 case UDF_ICB_FILETYPE_STREAMDIR : 3680 return S_IFDIR; 3681 case UDF_ICB_FILETYPE_FIFO : 3682 return S_IFIFO; 3683 case UDF_ICB_FILETYPE_CHARDEVICE : 3684 return S_IFCHR; 3685 case UDF_ICB_FILETYPE_BLOCKDEVICE : 3686 return S_IFBLK; 3687 case UDF_ICB_FILETYPE_RANDOMACCESS : 3688 case UDF_ICB_FILETYPE_REALTIME : 3689 return S_IFREG; 3690 case UDF_ICB_FILETYPE_SYMLINK : 3691 return S_IFLNK; 3692 case UDF_ICB_FILETYPE_SOCKET : 3693 return S_IFSOCK; 3694 } 3695 /* no idea what this is */ 3696 return 0; 3697 } 3698 3699 /* --------------------------------------------------------------------- */ 3700 3701 void 3702 udf_to_unix_name(char *result, int result_len, char *id, int len, 3703 struct charspec *chsp) 3704 { 3705 uint16_t *raw_name, *unix_name; 3706 uint16_t *inchp, ch; 3707 uint8_t *outchp; 3708 const char *osta_id = "OSTA Compressed Unicode"; 3709 int ucode_chars, nice_uchars, is_osta_typ0, nout; 3710 3711 raw_name = malloc(2048 * sizeof(uint16_t), M_UDFTEMP, M_WAITOK); 3712 unix_name = raw_name + 1024; /* split space in half */ 3713 assert(sizeof(char) == sizeof(uint8_t)); 3714 outchp = (uint8_t *) result; 3715 3716 is_osta_typ0 = (chsp->type == 0); 3717 is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0); 3718 if (is_osta_typ0) { 3719 /* TODO clean up */ 3720 *raw_name = *unix_name = 0; 3721 ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name); 3722 ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name)); 3723 nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars); 3724 /* output UTF8 */ 3725 for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) { 3726 ch = *inchp; 3727 nout = wput_utf8(outchp, result_len, ch); 3728 outchp += nout; result_len -= nout; 3729 if (!ch) break; 3730 } 3731 *outchp++ = 0; 3732 } else { 3733 /* assume 8bit char length byte latin-1 */ 3734 assert(*id == 8); 3735 assert(strlen((char *) (id+1)) <= MAXNAMLEN); 3736 strncpy((char *) result, (char *) (id+1), strlen((char *) (id+1))); 3737 } 3738 free(raw_name, M_UDFTEMP); 3739 } 3740 3741 /* --------------------------------------------------------------------- */ 3742 3743 void 3744 unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len, 3745 struct charspec *chsp) 3746 { 3747 uint16_t *raw_name; 3748 uint16_t *outchp; 3749 const char *inchp; 3750 const char *osta_id = "OSTA Compressed Unicode"; 3751 int udf_chars, is_osta_typ0, bits; 3752 size_t cnt; 3753 3754 /* allocate temporary unicode-16 buffer */ 3755 raw_name = malloc(1024, M_UDFTEMP, M_WAITOK); 3756 3757 /* convert utf8 to unicode-16 */ 3758 *raw_name = 0; 3759 inchp = name; 3760 outchp = raw_name; 3761 bits = 8; 3762 for (cnt = name_len, udf_chars = 0; cnt;) { 3763 /*###3490 [cc] warning: passing argument 2 of 'wget_utf8' from incompatible pointer type%%%*/ 3764 *outchp = wget_utf8(&inchp, &cnt); 3765 if (*outchp > 0xff) 3766 bits=16; 3767 outchp++; 3768 udf_chars++; 3769 } 3770 /* null terminate just in case */ 3771 *outchp++ = 0; 3772 3773 is_osta_typ0 = (chsp->type == 0); 3774 is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0); 3775 if (is_osta_typ0) { 3776 udf_chars = udf_CompressUnicode(udf_chars, bits, 3777 (unicode_t *) raw_name, 3778 (byte *) result); 3779 } else { 3780 printf("unix to udf name: no CHSP0 ?\n"); 3781 /* XXX assume 8bit char length byte latin-1 */ 3782 *result++ = 8; udf_chars = 1; 3783 strncpy(result, name + 1, name_len); 3784 udf_chars += name_len; 3785 } 3786 *result_len = udf_chars; 3787 free(raw_name, M_UDFTEMP); 3788 } 3789 3790 /* --------------------------------------------------------------------- */ 3791 3792 void 3793 udf_timestamp_to_timespec(struct udf_mount *ump, 3794 struct timestamp *timestamp, 3795 struct timespec *timespec) 3796 { 3797 struct clock_ymdhms ymdhms; 3798 uint32_t usecs, secs, nsecs; 3799 uint16_t tz; 3800 3801 /* fill in ymdhms structure from timestamp */ 3802 memset(&ymdhms, 0, sizeof(ymdhms)); 3803 ymdhms.dt_year = udf_rw16(timestamp->year); 3804 ymdhms.dt_mon = timestamp->month; 3805 ymdhms.dt_day = timestamp->day; 3806 ymdhms.dt_wday = 0; /* ? */ 3807 ymdhms.dt_hour = timestamp->hour; 3808 ymdhms.dt_min = timestamp->minute; 3809 ymdhms.dt_sec = timestamp->second; 3810 3811 secs = clock_ymdhms_to_secs(&ymdhms); 3812 usecs = timestamp->usec + 3813 100*timestamp->hund_usec + 10000*timestamp->centisec; 3814 nsecs = usecs * 1000; 3815 3816 /* 3817 * Calculate the time zone. The timezone is 12 bit signed 2's 3818 * compliment, so we gotta do some extra magic to handle it right. 3819 */ 3820 tz = udf_rw16(timestamp->type_tz); 3821 tz &= 0x0fff; /* only lower 12 bits are significant */ 3822 if (tz & 0x0800) /* sign extention */ 3823 tz |= 0xf000; 3824 3825 /* TODO check timezone conversion */ 3826 /* check if we are specified a timezone to convert */ 3827 if (udf_rw16(timestamp->type_tz) & 0x1000) { 3828 if ((int16_t) tz != -2047) 3829 secs -= (int16_t) tz * 60; 3830 } else { 3831 secs -= ump->mount_args.gmtoff; 3832 } 3833 3834 timespec->tv_sec = secs; 3835 timespec->tv_nsec = nsecs; 3836 } 3837 3838 3839 void 3840 udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp) 3841 { 3842 struct clock_ymdhms ymdhms; 3843 uint32_t husec, usec, csec; 3844 3845 (void) clock_secs_to_ymdhms(timespec->tv_sec, &ymdhms); 3846 3847 usec = timespec->tv_nsec / 1000; 3848 husec = usec / 100; 3849 usec -= husec * 100; /* only 0-99 in usec */ 3850 csec = husec / 100; /* only 0-99 in csec */ 3851 husec -= csec * 100; /* only 0-99 in husec */ 3852 3853 /* set method 1 for CUT/GMT */ 3854 timestamp->type_tz = udf_rw16((1<<12) + 0); 3855 timestamp->year = udf_rw16(ymdhms.dt_year); 3856 timestamp->month = ymdhms.dt_mon; 3857 timestamp->day = ymdhms.dt_day; 3858 timestamp->hour = ymdhms.dt_hour; 3859 timestamp->minute = ymdhms.dt_min; 3860 timestamp->second = ymdhms.dt_sec; 3861 timestamp->centisec = csec; 3862 timestamp->hund_usec = husec; 3863 timestamp->usec = usec; 3864 } 3865 3866 /* --------------------------------------------------------------------- */ 3867 3868 /* 3869 * Attribute and filetypes converters with get/set pairs 3870 */ 3871 3872 uint32_t 3873 udf_getaccessmode(struct udf_node *udf_node) 3874 { 3875 struct file_entry *fe = udf_node->fe;; 3876 struct extfile_entry *efe = udf_node->efe; 3877 uint32_t udf_perm, icbftype; 3878 uint32_t mode, ftype; 3879 uint16_t icbflags; 3880 3881 UDF_LOCK_NODE(udf_node, 0); 3882 if (fe) { 3883 udf_perm = udf_rw32(fe->perm); 3884 icbftype = fe->icbtag.file_type; 3885 icbflags = udf_rw16(fe->icbtag.flags); 3886 } else { 3887 assert(udf_node->efe); 3888 udf_perm = udf_rw32(efe->perm); 3889 icbftype = efe->icbtag.file_type; 3890 icbflags = udf_rw16(efe->icbtag.flags); 3891 } 3892 3893 mode = udf_perm_to_unix_mode(udf_perm); 3894 ftype = udf_icb_to_unix_filetype(icbftype); 3895 3896 /* set suid, sgid, sticky from flags in fe/efe */ 3897 if (icbflags & UDF_ICB_TAG_FLAGS_SETUID) 3898 mode |= S_ISUID; 3899 if (icbflags & UDF_ICB_TAG_FLAGS_SETGID) 3900 mode |= S_ISGID; 3901 if (icbflags & UDF_ICB_TAG_FLAGS_STICKY) 3902 mode |= S_ISVTX; 3903 3904 UDF_UNLOCK_NODE(udf_node, 0); 3905 3906 return mode | ftype; 3907 } 3908 3909 3910 void 3911 udf_setaccessmode(struct udf_node *udf_node, mode_t mode) 3912 { 3913 struct file_entry *fe = udf_node->fe; 3914 struct extfile_entry *efe = udf_node->efe; 3915 uint32_t udf_perm; 3916 uint16_t icbflags; 3917 3918 UDF_LOCK_NODE(udf_node, 0); 3919 udf_perm = unix_mode_to_udf_perm(mode & ALLPERMS); 3920 if (fe) { 3921 icbflags = udf_rw16(fe->icbtag.flags); 3922 } else { 3923 icbflags = udf_rw16(efe->icbtag.flags); 3924 } 3925 3926 icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID; 3927 icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID; 3928 icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY; 3929 if (mode & S_ISUID) 3930 icbflags |= UDF_ICB_TAG_FLAGS_SETUID; 3931 if (mode & S_ISGID) 3932 icbflags |= UDF_ICB_TAG_FLAGS_SETGID; 3933 if (mode & S_ISVTX) 3934 icbflags |= UDF_ICB_TAG_FLAGS_STICKY; 3935 3936 if (fe) { 3937 fe->perm = udf_rw32(udf_perm); 3938 fe->icbtag.flags = udf_rw16(icbflags); 3939 } else { 3940 efe->perm = udf_rw32(udf_perm); 3941 efe->icbtag.flags = udf_rw16(icbflags); 3942 } 3943 3944 UDF_UNLOCK_NODE(udf_node, 0); 3945 } 3946 3947 3948 void 3949 udf_getownership(struct udf_node *udf_node, uid_t *uidp, gid_t *gidp) 3950 { 3951 struct udf_mount *ump = udf_node->ump; 3952 struct file_entry *fe = udf_node->fe; 3953 struct extfile_entry *efe = udf_node->efe; 3954 uid_t uid; 3955 gid_t gid; 3956 3957 UDF_LOCK_NODE(udf_node, 0); 3958 if (fe) { 3959 uid = (uid_t)udf_rw32(fe->uid); 3960 gid = (gid_t)udf_rw32(fe->gid); 3961 } else { 3962 assert(udf_node->efe); 3963 uid = (uid_t)udf_rw32(efe->uid); 3964 gid = (gid_t)udf_rw32(efe->gid); 3965 } 3966 3967 /* do the uid/gid translation game */ 3968 if ((uid == (uid_t) -1) && (gid == (gid_t) -1)) { 3969 uid = ump->mount_args.anon_uid; 3970 gid = ump->mount_args.anon_gid; 3971 } 3972 *uidp = uid; 3973 *gidp = gid; 3974 3975 UDF_UNLOCK_NODE(udf_node, 0); 3976 } 3977 3978 3979 void 3980 udf_setownership(struct udf_node *udf_node, uid_t uid, gid_t gid) 3981 { 3982 struct udf_mount *ump = udf_node->ump; 3983 struct file_entry *fe = udf_node->fe; 3984 struct extfile_entry *efe = udf_node->efe; 3985 uid_t nobody_uid; 3986 gid_t nobody_gid; 3987 3988 UDF_LOCK_NODE(udf_node, 0); 3989 3990 /* do the uid/gid translation game */ 3991 nobody_uid = ump->mount_args.nobody_uid; 3992 nobody_gid = ump->mount_args.nobody_gid; 3993 if ((uid == nobody_uid) && (gid == nobody_gid)) { 3994 uid = (uid_t) -1; 3995 gid = (gid_t) -1; 3996 } 3997 3998 if (fe) { 3999 fe->uid = udf_rw32((uint32_t) uid); 4000 fe->gid = udf_rw32((uint32_t) gid); 4001 } else { 4002 efe->uid = udf_rw32((uint32_t) uid); 4003 efe->gid = udf_rw32((uint32_t) gid); 4004 } 4005 4006 UDF_UNLOCK_NODE(udf_node, 0); 4007 } 4008 4009 4010 /* --------------------------------------------------------------------- */ 4011 4012 4013 static int 4014 dirhash_fill(struct udf_node *dir_node) 4015 { 4016 struct vnode *dvp = dir_node->vnode; 4017 struct dirhash *dirh; 4018 struct file_entry *fe = dir_node->fe; 4019 struct extfile_entry *efe = dir_node->efe; 4020 struct fileid_desc *fid; 4021 struct dirent *dirent; 4022 uint64_t file_size, pre_diroffset, diroffset; 4023 uint32_t lb_size; 4024 int error; 4025 4026 /* make sure we have a dirhash to work on */ 4027 dirh = dir_node->dir_hash; 4028 KASSERT(dirh); 4029 KASSERT(dirh->refcnt > 0); 4030 4031 if (dirh->flags & DIRH_BROKEN) 4032 return EIO; 4033 if (dirh->flags & DIRH_COMPLETE) 4034 return 0; 4035 4036 /* make sure we have a clean dirhash to add to */ 4037 dirhash_purge_entries(dirh); 4038 4039 /* get directory filesize */ 4040 if (fe) { 4041 file_size = udf_rw64(fe->inf_len); 4042 } else { 4043 assert(efe); 4044 file_size = udf_rw64(efe->inf_len); 4045 } 4046 4047 /* allocate temporary space for fid */ 4048 lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 4049 fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); 4050 4051 /* allocate temporary space for dirent */ 4052 dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 4053 4054 error = 0; 4055 diroffset = 0; 4056 while (diroffset < file_size) { 4057 /* transfer a new fid/dirent */ 4058 pre_diroffset = diroffset; 4059 error = udf_read_fid_stream(dvp, &diroffset, fid, dirent); 4060 if (error) { 4061 /* TODO what to do? continue but not add? */ 4062 dirh->flags |= DIRH_BROKEN; 4063 dirhash_purge_entries(dirh); 4064 break; 4065 } 4066 4067 if ((fid->file_char & UDF_FILE_CHAR_DEL)) { 4068 /* register deleted extent for reuse */ 4069 dirhash_enter_freed(dirh, pre_diroffset, 4070 udf_fidsize(fid)); 4071 } else { 4072 /* append to the dirhash */ 4073 dirhash_enter(dirh, dirent, pre_diroffset, 4074 udf_fidsize(fid), 0); 4075 } 4076 } 4077 dirh->flags |= DIRH_COMPLETE; 4078 4079 free(fid, M_UDFTEMP); 4080 free(dirent, M_UDFTEMP); 4081 4082 return error; 4083 } 4084 4085 4086 /* --------------------------------------------------------------------- */ 4087 4088 /* 4089 * Directory read and manipulation functions. 4090 * 4091 * Note that if the file is found, the cached diroffset position *before* the 4092 * advance is remembered. Thus if the same filename is lookup again just after 4093 * this lookup its immediately found. 4094 */ 4095 4096 int 4097 udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, 4098 struct long_ad *icb_loc, int *found) 4099 { 4100 struct udf_node *dir_node = VTOI(vp); 4101 struct dirhash *dirh; 4102 struct dirhash_entry *dirh_ep; 4103 struct fileid_desc *fid; 4104 struct dirent *dirent; 4105 uint64_t diroffset; 4106 uint32_t lb_size; 4107 int hit, error; 4108 4109 /* set default return */ 4110 *found = 0; 4111 4112 /* get our dirhash and make sure its read in */ 4113 dirhash_get(&dir_node->dir_hash); 4114 error = dirhash_fill(dir_node); 4115 if (error) { 4116 dirhash_put(dir_node->dir_hash); 4117 return error; 4118 } 4119 dirh = dir_node->dir_hash; 4120 4121 /* allocate temporary space for fid */ 4122 lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 4123 fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); 4124 dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 4125 4126 DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n", 4127 namelen, namelen, name)); 4128 4129 /* search our dirhash hits */ 4130 memset(icb_loc, 0, sizeof(*icb_loc)); 4131 dirh_ep = NULL; 4132 for (;;) { 4133 hit = dirhash_lookup(dirh, name, namelen, &dirh_ep); 4134 /* if no hit, abort the search */ 4135 if (!hit) 4136 break; 4137 4138 /* check this hit */ 4139 diroffset = dirh_ep->offset; 4140 4141 /* transfer a new fid/dirent */ 4142 error = udf_read_fid_stream(vp, &diroffset, fid, dirent); 4143 if (error) 4144 break; 4145 4146 DPRINTF(DIRHASH, ("dirhash_lookup\tchecking `%*.*s`\n", 4147 dirent->d_namlen, dirent->d_namlen, dirent->d_name)); 4148 4149 /* see if its our entry */ 4150 KASSERT(dirent->d_namlen == namelen); 4151 if (strncmp(dirent->d_name, name, namelen) == 0) { 4152 *found = 1; 4153 *icb_loc = fid->icb; 4154 break; 4155 } 4156 } 4157 free(fid, M_UDFTEMP); 4158 free(dirent, M_UDFTEMP); 4159 4160 dirhash_put(dir_node->dir_hash); 4161 4162 return error; 4163 } 4164 4165 /* --------------------------------------------------------------------- */ 4166 4167 static int 4168 udf_create_new_fe(struct udf_mount *ump, struct file_entry *fe, int file_type, 4169 struct long_ad *node_icb, struct long_ad *parent_icb, 4170 uint64_t parent_unique_id) 4171 { 4172 struct timespec now; 4173 struct icb_tag *icb; 4174 struct filetimes_extattr_entry *ft_extattr; 4175 uint64_t unique_id; 4176 uint32_t fidsize, lb_num; 4177 uint8_t *bpos; 4178 int crclen, attrlen; 4179 4180 lb_num = udf_rw32(node_icb->loc.lb_num); 4181 udf_inittag(ump, &fe->tag, TAGID_FENTRY, lb_num); 4182 icb = &fe->icbtag; 4183 4184 /* 4185 * Always use strategy type 4 unless on WORM wich we don't support 4186 * (yet). Fill in defaults and set for internal allocation of data. 4187 */ 4188 icb->strat_type = udf_rw16(4); 4189 icb->max_num_entries = udf_rw16(1); 4190 icb->file_type = file_type; /* 8 bit */ 4191 icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC); 4192 4193 fe->perm = udf_rw32(0x7fff); /* all is allowed */ 4194 fe->link_cnt = udf_rw16(0); /* explicit setting */ 4195 4196 fe->ckpoint = udf_rw32(1); /* user supplied file version */ 4197 4198 vfs_timestamp(&now); 4199 udf_timespec_to_timestamp(&now, &fe->atime); 4200 udf_timespec_to_timestamp(&now, &fe->attrtime); 4201 udf_timespec_to_timestamp(&now, &fe->mtime); 4202 4203 udf_set_regid(&fe->imp_id, IMPL_NAME); 4204 udf_add_impl_regid(ump, &fe->imp_id); 4205 4206 unique_id = udf_advance_uniqueid(ump); 4207 fe->unique_id = udf_rw64(unique_id); 4208 fe->l_ea = udf_rw32(0); 4209 4210 /* create extended attribute to record our creation time */ 4211 attrlen = UDF_FILETIMES_ATTR_SIZE(1); 4212 ft_extattr = malloc(attrlen, M_UDFTEMP, M_WAITOK); 4213 memset(ft_extattr, 0, attrlen); 4214 ft_extattr->hdr.type = udf_rw32(UDF_FILETIMES_ATTR_NO); 4215 ft_extattr->hdr.subtype = 1; /* [4/48.10.5] */ 4216 ft_extattr->hdr.a_l = udf_rw32(UDF_FILETIMES_ATTR_SIZE(1)); 4217 ft_extattr->d_l = udf_rw32(UDF_TIMESTAMP_SIZE); /* one item */ 4218 ft_extattr->existence = UDF_FILETIMES_FILE_CREATION; 4219 udf_timespec_to_timestamp(&now, &ft_extattr->times[0]); 4220 4221 udf_extattr_insert_internal(ump, (union dscrptr *) fe, 4222 (struct extattr_entry *) ft_extattr); 4223 free(ft_extattr, M_UDFTEMP); 4224 4225 /* if its a directory, create '..' */ 4226 bpos = (uint8_t *) fe->data + udf_rw32(fe->l_ea); 4227 fidsize = 0; 4228 if (file_type == UDF_ICB_FILETYPE_DIRECTORY) { 4229 fidsize = udf_create_parentfid(ump, 4230 (struct fileid_desc *) bpos, parent_icb, 4231 parent_unique_id); 4232 } 4233 4234 /* record fidlength information */ 4235 fe->inf_len = udf_rw64(fidsize); 4236 fe->l_ad = udf_rw32(fidsize); 4237 fe->logblks_rec = udf_rw64(0); /* intern */ 4238 4239 crclen = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH; 4240 crclen += udf_rw32(fe->l_ea) + fidsize; 4241 fe->tag.desc_crc_len = udf_rw16(crclen); 4242 4243 (void) udf_validate_tag_and_crc_sums((union dscrptr *) fe); 4244 4245 return fidsize; 4246 } 4247 4248 /* --------------------------------------------------------------------- */ 4249 4250 static int 4251 udf_create_new_efe(struct udf_mount *ump, struct extfile_entry *efe, 4252 int file_type, struct long_ad *node_icb, struct long_ad *parent_icb, 4253 uint64_t parent_unique_id) 4254 { 4255 struct timespec now; 4256 struct icb_tag *icb; 4257 uint64_t unique_id; 4258 uint32_t fidsize, lb_num; 4259 uint8_t *bpos; 4260 int crclen; 4261 4262 lb_num = udf_rw32(node_icb->loc.lb_num); 4263 udf_inittag(ump, &efe->tag, TAGID_EXTFENTRY, lb_num); 4264 icb = &efe->icbtag; 4265 4266 /* 4267 * Always use strategy type 4 unless on WORM wich we don't support 4268 * (yet). Fill in defaults and set for internal allocation of data. 4269 */ 4270 icb->strat_type = udf_rw16(4); 4271 icb->max_num_entries = udf_rw16(1); 4272 icb->file_type = file_type; /* 8 bit */ 4273 icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC); 4274 4275 efe->perm = udf_rw32(0x7fff); /* all is allowed */ 4276 efe->link_cnt = udf_rw16(0); /* explicit setting */ 4277 4278 efe->ckpoint = udf_rw32(1); /* user supplied file version */ 4279 4280 vfs_timestamp(&now); 4281 udf_timespec_to_timestamp(&now, &efe->ctime); 4282 udf_timespec_to_timestamp(&now, &efe->atime); 4283 udf_timespec_to_timestamp(&now, &efe->attrtime); 4284 udf_timespec_to_timestamp(&now, &efe->mtime); 4285 4286 udf_set_regid(&efe->imp_id, IMPL_NAME); 4287 udf_add_impl_regid(ump, &efe->imp_id); 4288 4289 unique_id = udf_advance_uniqueid(ump); 4290 efe->unique_id = udf_rw64(unique_id); 4291 efe->l_ea = udf_rw32(0); 4292 4293 /* if its a directory, create '..' */ 4294 bpos = (uint8_t *) efe->data + udf_rw32(efe->l_ea); 4295 fidsize = 0; 4296 if (file_type == UDF_ICB_FILETYPE_DIRECTORY) { 4297 fidsize = udf_create_parentfid(ump, 4298 (struct fileid_desc *) bpos, parent_icb, 4299 parent_unique_id); 4300 } 4301 4302 /* record fidlength information */ 4303 efe->obj_size = udf_rw64(fidsize); 4304 efe->inf_len = udf_rw64(fidsize); 4305 efe->l_ad = udf_rw32(fidsize); 4306 efe->logblks_rec = udf_rw64(0); /* intern */ 4307 4308 crclen = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH; 4309 crclen += udf_rw32(efe->l_ea) + fidsize; 4310 efe->tag.desc_crc_len = udf_rw16(crclen); 4311 4312 (void) udf_validate_tag_and_crc_sums((union dscrptr *) efe); 4313 4314 return fidsize; 4315 } 4316 4317 /* --------------------------------------------------------------------- */ 4318 4319 int 4320 udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node, 4321 struct udf_node *udf_node, struct componentname *cnp) 4322 { 4323 struct vnode *dvp = dir_node->vnode; 4324 struct dirhash *dirh; 4325 struct dirhash_entry *dirh_ep; 4326 struct file_entry *fe = dir_node->fe; 4327 struct extfile_entry *efe = dir_node->efe; 4328 struct fileid_desc *fid; 4329 struct dirent *dirent; 4330 uint64_t file_size, diroffset; 4331 uint32_t lb_size, fidsize; 4332 int found, error; 4333 char const *name = cnp->cn_nameptr; 4334 int namelen = cnp->cn_namelen; 4335 int hit, refcnt; 4336 4337 /* get our dirhash and make sure its read in */ 4338 dirhash_get(&dir_node->dir_hash); 4339 error = dirhash_fill(dir_node); 4340 if (error) { 4341 dirhash_put(dir_node->dir_hash); 4342 return error; 4343 } 4344 dirh = dir_node->dir_hash; 4345 4346 /* get directory filesize */ 4347 if (fe) { 4348 file_size = udf_rw64(fe->inf_len); 4349 } else { 4350 assert(efe); 4351 file_size = udf_rw64(efe->inf_len); 4352 } 4353 4354 /* allocate temporary space for fid */ 4355 lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); 4356 fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); 4357 dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); 4358 4359 /* search our dirhash hits */ 4360 found = 0; 4361 dirh_ep = NULL; 4362 for (;;) { 4363 hit = dirhash_lookup(dirh, name, namelen, &dirh_ep); 4364 /* if no hit, abort the search */ 4365 if (!hit) 4366 break; 4367 4368 /* check this hit */ 4369 diroffset = dirh_ep->offset; 4370 4371 /* transfer a new fid/dirent */ 4372 error = udf_read_fid_stream(dvp, &diroffset, fid, dirent); 4373 if (error) 4374 break; 4375 4376 /* see if its our entry */ 4377 KASSERT(dirent->d_namlen == namelen); 4378 if (strncmp(dirent->d_name, name, namelen) == 0) { 4379 found = 1; 4380 break; 4381 } 4382 } 4383 4384 if (!found) 4385 error = ENOENT; 4386 if (error) 4387 goto error_out; 4388 4389 /* mark deleted */ 4390 fid->file_char |= UDF_FILE_CHAR_DEL; 4391 #ifdef UDF_COMPLETE_DELETE 4392 memset(&fid->icb, 0, sizeof(fid->icb)); 4393 #endif 4394 (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid); 4395 4396 /* get size of fid and compensate for the read_fid_stream advance */ 4397 fidsize = udf_fidsize(fid); 4398 diroffset -= fidsize; 4399 4400 /* write out */ 4401 error = vn_rdwr(UIO_WRITE, dir_node->vnode, 4402 fid, fidsize, diroffset, 4403 UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, 4404 FSCRED, NULL, NULL); 4405 if (error) 4406 goto error_out; 4407 4408 /* get reference count of attached node */ 4409 if (udf_node->fe) { 4410 refcnt = udf_rw16(udf_node->fe->link_cnt); 4411 } else { 4412 KASSERT(udf_node->efe); 4413 refcnt = udf_rw16(udf_node->efe->link_cnt); 4414 } 4415 #ifdef UDF_COMPLETE_DELETE 4416 /* substract reference counter in attached node */ 4417 refcnt -= 1; 4418 if (udf_node->fe) { 4419 udf_node->fe->link_cnt = udf_rw16(refcnt); 4420 } else { 4421 udf_node->efe->link_cnt = udf_rw16(refcnt); 4422 } 4423 4424 /* prevent writeout when refcnt == 0 */ 4425 if (refcnt == 0) 4426 udf_node->i_flags |= IN_DELETED; 4427 4428 if (fid->file_char & UDF_FILE_CHAR_DIR) { 4429 int drefcnt; 4430 4431 /* substract reference counter in directory node */ 4432 /* note subtract 2 (?) for its was also backreferenced */ 4433 if (dir_node->fe) { 4434 drefcnt = udf_rw16(dir_node->fe->link_cnt); 4435 drefcnt -= 1; 4436 dir_node->fe->link_cnt = udf_rw16(drefcnt); 4437 } else { 4438 KASSERT(dir_node->efe); 4439 drefcnt = udf_rw16(dir_node->efe->link_cnt); 4440 drefcnt -= 1; 4441 dir_node->efe->link_cnt = udf_rw16(drefcnt); 4442 } 4443 } 4444 4445 udf_node->i_flags |= IN_MODIFIED; 4446 dir_node->i_flags |= IN_MODIFIED; 4447 #endif 4448 /* if it is/was a hardlink adjust the file count */ 4449 if (refcnt > 0) 4450 udf_adjust_filecount(udf_node, -1); 4451 4452 /* remove from the dirhash */ 4453 dirhash_remove(dirh, dirent, diroffset, 4454 udf_fidsize(fid)); 4455 4456 error_out: 4457 free(fid, M_UDFTEMP); 4458 free(dirent, M_UDFTEMP); 4459 4460 dirhash_put(dir_node->dir_hash); 4461 4462 return error; 4463 } 4464 4465 /* --------------------------------------------------------------------- */ 4466 4467 /* 4468 * We are not allowed to split the fid tag itself over an logical block so 4469 * check the space remaining in the logical block. 4470 * 4471 * We try to select the smallest candidate for recycling or when none is 4472 * found, append a new one at the end of the directory. 4473 */ 4474 4475 int 4476 udf_dir_attach(struct udf_mount *ump, struct udf_node *dir_node, 4477 struct udf_node *udf_node, struct vattr *vap, struct componentname *cnp) 4478 { 4479 struct vnode *dvp = dir_node->vnode; 4480 struct dirhash *dirh; 4481 struct dirhash_entry *dirh_ep; 4482 struct fileid_desc *fid; 4483 struct icb_tag *icbtag; 4484 struct charspec osta_charspec; 4485 struct dirent dirent; 4486 uint64_t unique_id, dir_size, diroffset; 4487 uint64_t fid_pos, end_fid_pos, chosen_fid_pos; 4488 uint32_t chosen_size, chosen_size_diff; 4489 int lb_size, lb_rest, fidsize, this_fidsize, size_diff; 4490 int file_char, refcnt, icbflags, addr_type, hit, error; 4491 4492 /* get our dirhash and make sure its read in */ 4493 dirhash_get(&dir_node->dir_hash); 4494 error = dirhash_fill(dir_node); 4495 if (error) { 4496 dirhash_put(dir_node->dir_hash); 4497 return error; 4498 } 4499 dirh = dir_node->dir_hash; 4500 4501 /* get info */ 4502 lb_size = udf_rw32(ump->logical_vol->lb_size); 4503 udf_osta_charset(&osta_charspec); 4504 4505 if (dir_node->fe) { 4506 dir_size = udf_rw64(dir_node->fe->inf_len); 4507 icbtag = &dir_node->fe->icbtag; 4508 } else { 4509 dir_size = udf_rw64(dir_node->efe->inf_len); 4510 icbtag = &dir_node->efe->icbtag; 4511 } 4512 4513 icbflags = udf_rw16(icbtag->flags); 4514 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 4515 4516 if (udf_node->fe) { 4517 unique_id = udf_rw64(udf_node->fe->unique_id); 4518 refcnt = udf_rw16(udf_node->fe->link_cnt); 4519 } else { 4520 unique_id = udf_rw64(udf_node->efe->unique_id); 4521 refcnt = udf_rw16(udf_node->efe->link_cnt); 4522 } 4523 4524 if (refcnt > 0) { 4525 unique_id = udf_advance_uniqueid(ump); 4526 udf_adjust_filecount(udf_node, 1); 4527 } 4528 4529 /* determine file characteristics */ 4530 file_char = 0; /* visible non deleted file and not stream metadata */ 4531 if (vap->va_type == VDIR) 4532 file_char = UDF_FILE_CHAR_DIR; 4533 4534 /* malloc scrap buffer */ 4535 fid = malloc(lb_size, M_TEMP, M_WAITOK); 4536 bzero(fid, lb_size); 4537 4538 /* calculate _minimum_ fid size */ 4539 unix_to_udf_name((char *) fid->data, &fid->l_fi, 4540 cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec); 4541 fidsize = UDF_FID_SIZE + fid->l_fi; 4542 fidsize = (fidsize + 3) & ~3; /* multiple of 4 */ 4543 4544 /* find position that will fit the FID */ 4545 chosen_fid_pos = dir_size; 4546 chosen_size = 0; 4547 chosen_size_diff = UINT_MAX; 4548 4549 /* shut up gcc */ 4550 dirent.d_namlen = 0; 4551 4552 /* search our dirhash hits */ 4553 error = 0; 4554 dirh_ep = NULL; 4555 for (;;) { 4556 hit = dirhash_lookup_freed(dirh, fidsize, &dirh_ep); 4557 /* if no hit, abort the search */ 4558 if (!hit) 4559 break; 4560 4561 /* check this hit for size */ 4562 this_fidsize = dirh_ep->entry_size; 4563 4564 /* check this hit */ 4565 fid_pos = dirh_ep->offset; 4566 end_fid_pos = fid_pos + this_fidsize; 4567 size_diff = this_fidsize - fidsize; 4568 lb_rest = lb_size - (end_fid_pos % lb_size); 4569 4570 #ifndef UDF_COMPLETE_DELETE 4571 /* transfer a new fid/dirent */ 4572 error = udf_read_fid_stream(vp, &fid_pos, fid, dirent); 4573 if (error) 4574 goto error_out; 4575 4576 /* only reuse entries that are wiped */ 4577 /* check if the len + loc are marked zero */ 4578 if (udf_rw32(fid->icb.len != 0)) 4579 continue; 4580 if (udf_rw32(fid->icb.loc.lb_num) != 0) 4581 continue; 4582 if (udf_rw16(fid->icb.loc.part_num != 0)) 4583 continue; 4584 #endif /* UDF_COMPLETE_DELETE */ 4585 4586 /* select if not splitting the tag and its smaller */ 4587 if ((size_diff >= 0) && 4588 (size_diff < chosen_size_diff) && 4589 (lb_rest >= sizeof(struct desc_tag))) 4590 { 4591 /* UDF 2.3.4.2+3 specifies rules for iu size */ 4592 if ((size_diff == 0) || (size_diff >= 32)) { 4593 chosen_fid_pos = fid_pos; 4594 chosen_size = this_fidsize; 4595 chosen_size_diff = size_diff; 4596 } 4597 } 4598 } 4599 4600 4601 /* extend directory if no other candidate found */ 4602 if (chosen_size == 0) { 4603 chosen_fid_pos = dir_size; 4604 chosen_size = fidsize; 4605 chosen_size_diff = 0; 4606 4607 /* special case UDF 2.00+ 2.3.4.4, no splitting up fid tag */ 4608 if (addr_type == UDF_ICB_INTERN_ALLOC) { 4609 /* pre-grow directory to see if we're to switch */ 4610 udf_grow_node(dir_node, dir_size + chosen_size); 4611 4612 icbflags = udf_rw16(icbtag->flags); 4613 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 4614 } 4615 4616 /* make sure the next fid desc_tag won't be splitted */ 4617 if (addr_type != UDF_ICB_INTERN_ALLOC) { 4618 end_fid_pos = chosen_fid_pos + chosen_size; 4619 lb_rest = lb_size - (end_fid_pos % lb_size); 4620 4621 /* pad with implementation use regid if needed */ 4622 if (lb_rest < sizeof(struct desc_tag)) 4623 chosen_size += 32; 4624 } 4625 } 4626 chosen_size_diff = chosen_size - fidsize; 4627 diroffset = chosen_fid_pos + chosen_size; 4628 4629 /* populate the FID */ 4630 memset(fid, 0, lb_size); 4631 udf_inittag(ump, &fid->tag, TAGID_FID, 0); 4632 fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */ 4633 fid->file_char = file_char; 4634 fid->icb = udf_node->loc; 4635 fid->icb.longad_uniqueid = udf_rw32((uint32_t) unique_id); 4636 fid->l_iu = udf_rw16(0); 4637 4638 if (chosen_size > fidsize) { 4639 /* insert implementation-use regid to space it correctly */ 4640 fid->l_iu = udf_rw16(chosen_size_diff); 4641 4642 /* set implementation use */ 4643 udf_set_regid((struct regid *) fid->data, IMPL_NAME); 4644 udf_add_impl_regid(ump, (struct regid *) fid->data); 4645 } 4646 4647 /* fill in name */ 4648 unix_to_udf_name((char *) fid->data + udf_rw16(fid->l_iu), 4649 &fid->l_fi, cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec); 4650 4651 fid->tag.desc_crc_len = chosen_size - UDF_DESC_TAG_LENGTH; 4652 (void) udf_validate_tag_and_crc_sums((union dscrptr *) fid); 4653 4654 /* writeout FID/update parent directory */ 4655 error = vn_rdwr(UIO_WRITE, dvp, 4656 fid, chosen_size, chosen_fid_pos, 4657 UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, 4658 FSCRED, NULL, NULL); 4659 4660 if (error) 4661 goto error_out; 4662 4663 /* add reference counter in attached node */ 4664 if (udf_node->fe) { 4665 refcnt = udf_rw16(udf_node->fe->link_cnt); 4666 udf_node->fe->link_cnt = udf_rw16(refcnt+1); 4667 } else { 4668 KASSERT(udf_node->efe); 4669 refcnt = udf_rw16(udf_node->efe->link_cnt); 4670 udf_node->efe->link_cnt = udf_rw16(refcnt+1); 4671 } 4672 4673 /* mark not deleted if it was... just in case, but do warn */ 4674 if (udf_node->i_flags & IN_DELETED) { 4675 printf("udf: warning, marking a file undeleted\n"); 4676 udf_node->i_flags &= ~IN_DELETED; 4677 } 4678 4679 if (file_char & UDF_FILE_CHAR_DIR) { 4680 /* add reference counter in directory node for '..' */ 4681 if (dir_node->fe) { 4682 refcnt = udf_rw16(dir_node->fe->link_cnt); 4683 refcnt++; 4684 dir_node->fe->link_cnt = udf_rw16(refcnt); 4685 } else { 4686 KASSERT(dir_node->efe); 4687 refcnt = udf_rw16(dir_node->efe->link_cnt); 4688 refcnt++; 4689 dir_node->efe->link_cnt = udf_rw16(refcnt); 4690 } 4691 } 4692 4693 /* append to the dirhash */ 4694 dirent.d_namlen = cnp->cn_namelen; 4695 memcpy(dirent.d_name, cnp->cn_nameptr, cnp->cn_namelen); 4696 dirhash_enter(dirh, &dirent, chosen_fid_pos, 4697 udf_fidsize(fid), 1); 4698 4699 /* note updates */ 4700 udf_node->i_flags |= IN_CHANGE | IN_MODIFY; /* | IN_CREATE? */ 4701 /* VN_KNOTE(udf_node, ...) */ 4702 udf_update(udf_node->vnode, NULL, NULL, NULL, 0); 4703 4704 error_out: 4705 free(fid, M_TEMP); 4706 4707 dirhash_put(dir_node->dir_hash); 4708 4709 return error; 4710 } 4711 4712 /* --------------------------------------------------------------------- */ 4713 4714 /* 4715 * Each node can have an attached streamdir node though not recursively. These 4716 * are otherwise known as named substreams/named extended attributes that have 4717 * no size limitations. 4718 * 4719 * `Normal' extended attributes are indicated with a number and are recorded 4720 * in either the fe/efe descriptor itself for small descriptors or recorded in 4721 * the attached extended attribute file. Since these spaces can get 4722 * fragmented, care ought to be taken. 4723 * 4724 * Since the size of the space reserved for allocation descriptors is limited, 4725 * there is a mechanim provided for extending this space; this is done by a 4726 * special extent to allow schrinking of the allocations without breaking the 4727 * linkage to the allocation extent descriptor. 4728 */ 4729 4730 int 4731 udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, 4732 struct udf_node **udf_noderes) 4733 { 4734 union dscrptr *dscr; 4735 struct udf_node *udf_node; 4736 struct vnode *nvp; 4737 struct long_ad icb_loc, last_fe_icb_loc; 4738 uint64_t file_size; 4739 uint32_t lb_size, sector, dummy; 4740 uint8_t *file_data; 4741 int udf_file_type, dscr_type, strat, strat4096, needs_indirect; 4742 int slot, eof, error; 4743 4744 DPRINTF(NODE, ("udf_get_node called\n")); 4745 *udf_noderes = udf_node = NULL; 4746 4747 /* lock to disallow simultanious creation of same udf_node */ 4748 mutex_enter(&ump->get_node_lock); 4749 4750 DPRINTF(NODE, ("\tlookup in hash table\n")); 4751 /* lookup in hash table */ 4752 assert(ump); 4753 assert(node_icb_loc); 4754 udf_node = udf_hash_lookup(ump, node_icb_loc); 4755 if (udf_node) { 4756 DPRINTF(NODE, ("\tgot it from the hash!\n")); 4757 /* vnode is returned locked */ 4758 *udf_noderes = udf_node; 4759 mutex_exit(&ump->get_node_lock); 4760 return 0; 4761 } 4762 4763 /* garbage check: translate udf_node_icb_loc to sectornr */ 4764 error = udf_translate_vtop(ump, node_icb_loc, §or, &dummy); 4765 if (error) { 4766 /* no use, this will fail anyway */ 4767 mutex_exit(&ump->get_node_lock); 4768 return EINVAL; 4769 } 4770 4771 /* build udf_node (do initialise!) */ 4772 udf_node = pool_get(&udf_node_pool, PR_WAITOK); 4773 memset(udf_node, 0, sizeof(struct udf_node)); 4774 4775 DPRINTF(NODE, ("\tget new vnode\n")); 4776 /* give it a vnode */ 4777 error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, &nvp); 4778 if (error) { 4779 pool_put(&udf_node_pool, udf_node); 4780 mutex_exit(&ump->get_node_lock); 4781 return error; 4782 } 4783 4784 /* always return locked vnode */ 4785 if ((error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY))) { 4786 /* recycle vnode and unlock; simultanious will fail too */ 4787 ungetnewvnode(nvp); 4788 mutex_exit(&ump->get_node_lock); 4789 return error; 4790 } 4791 4792 /* initialise crosslinks, note location of fe/efe for hashing */ 4793 udf_node->ump = ump; 4794 udf_node->vnode = nvp; 4795 nvp->v_data = udf_node; 4796 udf_node->loc = *node_icb_loc; 4797 udf_node->lockf = 0; 4798 mutex_init(&udf_node->node_mutex, MUTEX_DEFAULT, IPL_NONE); 4799 cv_init(&udf_node->node_lock, "udf_nlk"); 4800 genfs_node_init(nvp, &udf_genfsops); /* inititise genfs */ 4801 udf_node->outstanding_bufs = 0; 4802 udf_node->outstanding_nodedscr = 0; 4803 4804 /* insert into the hash lookup */ 4805 udf_register_node(udf_node); 4806 4807 /* safe to unlock, the entry is in the hash table, vnode is locked */ 4808 mutex_exit(&ump->get_node_lock); 4809 4810 icb_loc = *node_icb_loc; 4811 needs_indirect = 0; 4812 strat4096 = 0; 4813 udf_file_type = UDF_ICB_FILETYPE_UNKNOWN; 4814 file_size = 0; 4815 file_data = NULL; 4816 lb_size = udf_rw32(ump->logical_vol->lb_size); 4817 4818 DPRINTF(NODE, ("\tstart reading descriptors\n")); 4819 do { 4820 /* try to read in fe/efe */ 4821 error = udf_read_logvol_dscr(ump, &icb_loc, &dscr); 4822 4823 /* blank sector marks end of sequence, check this */ 4824 if ((dscr == NULL) && (!strat4096)) 4825 error = ENOENT; 4826 4827 /* break if read error or blank sector */ 4828 if (error || (dscr == NULL)) 4829 break; 4830 4831 /* process descriptor based on the descriptor type */ 4832 dscr_type = udf_rw16(dscr->tag.id); 4833 DPRINTF(NODE, ("\tread descriptor %d\n", dscr_type)); 4834 4835 /* if dealing with an indirect entry, follow the link */ 4836 if (dscr_type == TAGID_INDIRECTENTRY) { 4837 needs_indirect = 0; 4838 udf_free_logvol_dscr(ump, &icb_loc, dscr); 4839 icb_loc = dscr->inde.indirect_icb; 4840 continue; 4841 } 4842 4843 /* only file entries and extended file entries allowed here */ 4844 if ((dscr_type != TAGID_FENTRY) && 4845 (dscr_type != TAGID_EXTFENTRY)) { 4846 udf_free_logvol_dscr(ump, &icb_loc, dscr); 4847 error = ENOENT; 4848 break; 4849 } 4850 4851 KASSERT(udf_tagsize(dscr, lb_size) == lb_size); 4852 4853 /* choose this one */ 4854 last_fe_icb_loc = icb_loc; 4855 4856 /* record and process/update (ext)fentry */ 4857 file_data = NULL; 4858 if (dscr_type == TAGID_FENTRY) { 4859 if (udf_node->fe) 4860 udf_free_logvol_dscr(ump, &last_fe_icb_loc, 4861 udf_node->fe); 4862 udf_node->fe = &dscr->fe; 4863 strat = udf_rw16(udf_node->fe->icbtag.strat_type); 4864 udf_file_type = udf_node->fe->icbtag.file_type; 4865 file_size = udf_rw64(udf_node->fe->inf_len); 4866 file_data = udf_node->fe->data; 4867 } else { 4868 if (udf_node->efe) 4869 udf_free_logvol_dscr(ump, &last_fe_icb_loc, 4870 udf_node->efe); 4871 udf_node->efe = &dscr->efe; 4872 strat = udf_rw16(udf_node->efe->icbtag.strat_type); 4873 udf_file_type = udf_node->efe->icbtag.file_type; 4874 file_size = udf_rw64(udf_node->efe->inf_len); 4875 file_data = udf_node->efe->data; 4876 } 4877 4878 /* check recording strategy (structure) */ 4879 4880 /* 4881 * Strategy 4096 is a daisy linked chain terminating with an 4882 * unrecorded sector or a TERM descriptor. The next 4883 * descriptor is to be found in the sector that follows the 4884 * current sector. 4885 */ 4886 if (strat == 4096) { 4887 strat4096 = 1; 4888 needs_indirect = 1; 4889 4890 icb_loc.loc.lb_num = udf_rw32(icb_loc.loc.lb_num) + 1; 4891 } 4892 4893 /* 4894 * Strategy 4 is the normal strategy and terminates, but if 4895 * we're in strategy 4096, we can't have strategy 4 mixed in 4896 */ 4897 4898 if (strat == 4) { 4899 if (strat4096) { 4900 error = EINVAL; 4901 break; 4902 } 4903 break; /* done */ 4904 } 4905 } while (!error); 4906 4907 /* first round of cleanup code */ 4908 if (error) { 4909 DPRINTF(NODE, ("\tnode fe/efe failed!\n")); 4910 /* recycle udf_node */ 4911 udf_dispose_node(udf_node); 4912 4913 vlockmgr(nvp->v_vnlock, LK_RELEASE); 4914 nvp->v_data = NULL; 4915 ungetnewvnode(nvp); 4916 4917 return EINVAL; /* error code ok? */ 4918 } 4919 DPRINTF(NODE, ("\tnode fe/efe read in fine\n")); 4920 4921 /* assert no references to dscr anymore beyong this point */ 4922 assert((udf_node->fe) || (udf_node->efe)); 4923 dscr = NULL; 4924 4925 /* 4926 * Remember where to record an updated version of the descriptor. If 4927 * there is a sequence of indirect entries, icb_loc will have been 4928 * updated. Its the write disipline to allocate new space and to make 4929 * sure the chain is maintained. 4930 * 4931 * `needs_indirect' flags if the next location is to be filled with 4932 * with an indirect entry. 4933 */ 4934 udf_node->write_loc = icb_loc; 4935 udf_node->needs_indirect = needs_indirect; 4936 4937 /* 4938 * Go trough all allocations extents of this descriptor and when 4939 * encountering a redirect read in the allocation extension. These are 4940 * daisy-chained. 4941 */ 4942 UDF_LOCK_NODE(udf_node, 0); 4943 udf_node->num_extensions = 0; 4944 4945 error = 0; 4946 slot = 0; 4947 for (;;) { 4948 udf_get_adslot(udf_node, slot, &icb_loc, &eof); 4949 DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, len = %d, " 4950 "lb_num = %d, part = %d\n", slot, eof, 4951 UDF_EXT_FLAGS(udf_rw32(icb_loc.len)), 4952 UDF_EXT_LEN(udf_rw32(icb_loc.len)), 4953 udf_rw32(icb_loc.loc.lb_num), 4954 udf_rw16(icb_loc.loc.part_num))); 4955 if (eof) 4956 break; 4957 slot++; 4958 4959 if (UDF_EXT_FLAGS(udf_rw32(icb_loc.len)) != UDF_EXT_REDIRECT) 4960 continue; 4961 4962 DPRINTF(NODE, ("\tgot redirect extent\n")); 4963 if (udf_node->num_extensions >= UDF_MAX_ALLOC_EXTENTS) { 4964 DPRINTF(ALLOC, ("udf_get_node: implementation limit, " 4965 "too many allocation extensions on " 4966 "udf_node\n")); 4967 error = EINVAL; 4968 break; 4969 } 4970 4971 /* length can only be *one* lb : UDF 2.50/2.3.7.1 */ 4972 if (UDF_EXT_LEN(udf_rw32(icb_loc.len)) != lb_size) { 4973 DPRINTF(ALLOC, ("udf_get_node: bad allocation " 4974 "extension size in udf_node\n")); 4975 error = EINVAL; 4976 break; 4977 } 4978 4979 DPRINTF(NODE, ("read allocation extent at lb_num %d\n", 4980 UDF_EXT_LEN(udf_rw32(icb_loc.loc.lb_num)))); 4981 /* load in allocation extent */ 4982 error = udf_read_logvol_dscr(ump, &icb_loc, &dscr); 4983 if (error || (dscr == NULL)) 4984 break; 4985 4986 /* process read-in descriptor */ 4987 dscr_type = udf_rw16(dscr->tag.id); 4988 4989 if (dscr_type != TAGID_ALLOCEXTENT) { 4990 udf_free_logvol_dscr(ump, &icb_loc, dscr); 4991 error = ENOENT; 4992 break; 4993 } 4994 4995 DPRINTF(NODE, ("\trecording redirect extent\n")); 4996 udf_node->ext[udf_node->num_extensions] = &dscr->aee; 4997 udf_node->ext_loc[udf_node->num_extensions] = icb_loc; 4998 4999 udf_node->num_extensions++; 5000 5001 } /* while */ 5002 UDF_UNLOCK_NODE(udf_node, 0); 5003 5004 /* second round of cleanup code */ 5005 if (error) { 5006 /* recycle udf_node */ 5007 udf_dispose_node(udf_node); 5008 5009 vlockmgr(nvp->v_vnlock, LK_RELEASE); 5010 nvp->v_data = NULL; 5011 ungetnewvnode(nvp); 5012 5013 return EINVAL; /* error code ok? */ 5014 } 5015 5016 DPRINTF(NODE, ("\tnode read in fine\n")); 5017 5018 /* 5019 * Translate UDF filetypes into vnode types. 5020 * 5021 * Systemfiles like the meta main and mirror files are not treated as 5022 * normal files, so we type them as having no type. UDF dictates that 5023 * they are not allowed to be visible. 5024 */ 5025 5026 switch (udf_file_type) { 5027 case UDF_ICB_FILETYPE_DIRECTORY : 5028 case UDF_ICB_FILETYPE_STREAMDIR : 5029 nvp->v_type = VDIR; 5030 break; 5031 case UDF_ICB_FILETYPE_BLOCKDEVICE : 5032 nvp->v_type = VBLK; 5033 break; 5034 case UDF_ICB_FILETYPE_CHARDEVICE : 5035 nvp->v_type = VCHR; 5036 break; 5037 case UDF_ICB_FILETYPE_SOCKET : 5038 nvp->v_type = VSOCK; 5039 break; 5040 case UDF_ICB_FILETYPE_FIFO : 5041 nvp->v_type = VFIFO; 5042 break; 5043 case UDF_ICB_FILETYPE_SYMLINK : 5044 nvp->v_type = VLNK; 5045 break; 5046 case UDF_ICB_FILETYPE_VAT : 5047 case UDF_ICB_FILETYPE_META_MAIN : 5048 case UDF_ICB_FILETYPE_META_MIRROR : 5049 nvp->v_type = VNON; 5050 break; 5051 case UDF_ICB_FILETYPE_RANDOMACCESS : 5052 case UDF_ICB_FILETYPE_REALTIME : 5053 nvp->v_type = VREG; 5054 break; 5055 default: 5056 /* YIKES, something else */ 5057 nvp->v_type = VNON; 5058 } 5059 5060 /* TODO specfs, fifofs etc etc. vnops setting */ 5061 5062 /* don't forget to set vnode's v_size */ 5063 uvm_vnp_setsize(nvp, file_size); 5064 5065 /* TODO ext attr and streamdir udf_nodes */ 5066 5067 *udf_noderes = udf_node; 5068 5069 return 0; 5070 } 5071 5072 /* --------------------------------------------------------------------- */ 5073 5074 int 5075 udf_writeout_node(struct udf_node *udf_node, int waitfor) 5076 { 5077 union dscrptr *dscr; 5078 struct long_ad *loc; 5079 int extnr, flags, error; 5080 5081 DPRINTF(NODE, ("udf_writeout_node called\n")); 5082 5083 KASSERT(udf_node->outstanding_bufs == 0); 5084 KASSERT(udf_node->outstanding_nodedscr == 0); 5085 5086 KASSERT(LIST_EMPTY(&udf_node->vnode->v_dirtyblkhd)); 5087 5088 if (udf_node->i_flags & IN_DELETED) { 5089 DPRINTF(NODE, ("\tnode deleted; not writing out\n")); 5090 return 0; 5091 } 5092 5093 /* lock node */ 5094 flags = waitfor ? 0 : IN_CALLBACK_ULK; 5095 UDF_LOCK_NODE(udf_node, flags); 5096 5097 /* at least one descriptor writeout */ 5098 udf_node->outstanding_nodedscr = 1; 5099 5100 /* we're going to write out the descriptor so clear the flags */ 5101 udf_node->i_flags &= ~(IN_MODIFIED | IN_ACCESSED); 5102 5103 /* if we were rebuild, write out the allocation extents */ 5104 if (udf_node->i_flags & IN_NODE_REBUILD) { 5105 /* mark outstanding node descriptors and issue them */ 5106 udf_node->outstanding_nodedscr += udf_node->num_extensions; 5107 for (extnr = 0; extnr < udf_node->num_extensions; extnr++) { 5108 loc = &udf_node->ext_loc[extnr]; 5109 dscr = (union dscrptr *) udf_node->ext[extnr]; 5110 error = udf_write_logvol_dscr(udf_node, dscr, loc, 0); 5111 if (error) 5112 return error; 5113 } 5114 /* mark allocation extents written out */ 5115 udf_node->i_flags &= ~(IN_NODE_REBUILD); 5116 } 5117 5118 if (udf_node->fe) { 5119 KASSERT(udf_node->efe == NULL); 5120 dscr = (union dscrptr *) udf_node->fe; 5121 } else { 5122 KASSERT(udf_node->efe); 5123 KASSERT(udf_node->fe == NULL); 5124 dscr = (union dscrptr *) udf_node->efe; 5125 } 5126 KASSERT(dscr); 5127 5128 loc = &udf_node->write_loc; 5129 error = udf_write_logvol_dscr(udf_node, dscr, loc, waitfor); 5130 return error; 5131 } 5132 5133 /* --------------------------------------------------------------------- */ 5134 5135 int 5136 udf_dispose_node(struct udf_node *udf_node) 5137 { 5138 struct vnode *vp; 5139 int extnr; 5140 5141 DPRINTF(NODE, ("udf_dispose_node called on node %p\n", udf_node)); 5142 if (!udf_node) { 5143 DPRINTF(NODE, ("UDF: Dispose node on node NULL, ignoring\n")); 5144 return 0; 5145 } 5146 5147 vp = udf_node->vnode; 5148 #ifdef DIAGNOSTIC 5149 if (vp->v_numoutput) 5150 panic("disposing UDF node with pending I/O's, udf_node = %p, " 5151 "v_numoutput = %d", udf_node, vp->v_numoutput); 5152 #endif 5153 5154 /* wait until out of sync (just in case we happen to stumble over one */ 5155 KASSERT(!mutex_owned(&mntvnode_lock)); 5156 mutex_enter(&mntvnode_lock); 5157 while (udf_node->i_flags & IN_SYNCED) { 5158 cv_timedwait(&udf_node->ump->dirtynodes_cv, &mntvnode_lock, 5159 hz/16); 5160 } 5161 mutex_exit(&mntvnode_lock); 5162 5163 /* TODO extended attributes and streamdir */ 5164 5165 /* remove dirhash if present */ 5166 dirhash_purge(&udf_node->dir_hash); 5167 5168 /* remove from our hash lookup table */ 5169 udf_deregister_node(udf_node); 5170 5171 /* destroy our lock */ 5172 mutex_destroy(&udf_node->node_mutex); 5173 cv_destroy(&udf_node->node_lock); 5174 5175 /* dissociate our udf_node from the vnode */ 5176 genfs_node_destroy(udf_node->vnode); 5177 vp->v_data = NULL; 5178 5179 /* free associated memory and the node itself */ 5180 for (extnr = 0; extnr < udf_node->num_extensions; extnr++) { 5181 udf_free_logvol_dscr(udf_node->ump, &udf_node->ext_loc[extnr], 5182 udf_node->ext[extnr]); 5183 udf_node->ext[extnr] = (void *) 0xdeadcccc; 5184 } 5185 5186 if (udf_node->fe) 5187 udf_free_logvol_dscr(udf_node->ump, &udf_node->loc, 5188 udf_node->fe); 5189 if (udf_node->efe) 5190 udf_free_logvol_dscr(udf_node->ump, &udf_node->loc, 5191 udf_node->efe); 5192 5193 udf_node->fe = (void *) 0xdeadaaaa; 5194 udf_node->efe = (void *) 0xdeadbbbb; 5195 udf_node->ump = (void *) 0xdeadbeef; 5196 pool_put(&udf_node_pool, udf_node); 5197 5198 return 0; 5199 } 5200 5201 5202 5203 /* 5204 * create a new node using the specified vnodeops, vap and cnp but with the 5205 * udf_file_type. This allows special files to be created. Use with care. 5206 */ 5207 5208 static int 5209 udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type, 5210 int (**vnodeops)(void *), struct vattr *vap, struct componentname *cnp) 5211 { 5212 union dscrptr *dscr; 5213 struct udf_node *dir_node = VTOI(dvp);; 5214 struct udf_node *udf_node; 5215 struct udf_mount *ump = dir_node->ump; 5216 struct vnode *nvp; 5217 struct long_ad node_icb_loc; 5218 uint64_t parent_unique_id; 5219 uint64_t lmapping; 5220 uint32_t lb_size, lb_num; 5221 uint16_t vpart_num; 5222 uid_t uid; 5223 gid_t gid, parent_gid; 5224 int fid_size, error; 5225 5226 lb_size = udf_rw32(ump->logical_vol->lb_size); 5227 *vpp = NULL; 5228 5229 /* allocate vnode */ 5230 error = getnewvnode(VT_UDF, ump->vfs_mountp, vnodeops, &nvp); 5231 if (error) 5232 return error; 5233 5234 /* lock node */ 5235 error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY); 5236 if (error) { 5237 nvp->v_data = NULL; 5238 ungetnewvnode(nvp); 5239 return error; 5240 } 5241 5242 /* get disc allocation for one logical block */ 5243 vpart_num = ump->node_part; 5244 error = udf_pre_allocate_space(ump, UDF_C_NODE, 1, 5245 vpart_num, &lmapping); 5246 lb_num = lmapping; 5247 if (error) { 5248 vlockmgr(nvp->v_vnlock, LK_RELEASE); 5249 ungetnewvnode(nvp); 5250 return error; 5251 } 5252 5253 /* initialise pointer to location */ 5254 memset(&node_icb_loc, 0, sizeof(struct long_ad)); 5255 node_icb_loc.len = lb_size; 5256 node_icb_loc.loc.lb_num = udf_rw32(lb_num); 5257 node_icb_loc.loc.part_num = udf_rw16(vpart_num); 5258 5259 /* build udf_node (do initialise!) */ 5260 udf_node = pool_get(&udf_node_pool, PR_WAITOK); 5261 memset(udf_node, 0, sizeof(struct udf_node)); 5262 5263 /* initialise crosslinks, note location of fe/efe for hashing */ 5264 /* bugalert: synchronise with udf_get_node() */ 5265 udf_node->ump = ump; 5266 udf_node->vnode = nvp; 5267 nvp->v_data = udf_node; 5268 udf_node->loc = node_icb_loc; 5269 udf_node->write_loc = node_icb_loc; 5270 udf_node->lockf = 0; 5271 mutex_init(&udf_node->node_mutex, MUTEX_DEFAULT, IPL_NONE); 5272 cv_init(&udf_node->node_lock, "udf_nlk"); 5273 udf_node->outstanding_bufs = 0; 5274 udf_node->outstanding_nodedscr = 0; 5275 5276 /* initialise genfs */ 5277 genfs_node_init(nvp, &udf_genfsops); 5278 5279 /* insert into the hash lookup */ 5280 udf_register_node(udf_node); 5281 5282 /* get parent's unique ID for refering '..' if its a directory */ 5283 if (dir_node->fe) { 5284 parent_unique_id = udf_rw64(dir_node->fe->unique_id); 5285 parent_gid = (gid_t) udf_rw32(dir_node->fe->gid); 5286 } else { 5287 parent_unique_id = udf_rw64(dir_node->efe->unique_id); 5288 parent_gid = (gid_t) udf_rw32(dir_node->efe->gid); 5289 } 5290 5291 /* get descriptor */ 5292 udf_create_logvol_dscr(ump, udf_node, &node_icb_loc, &dscr); 5293 5294 /* choose a fe or an efe for it */ 5295 if (ump->logical_vol->tag.descriptor_ver == 2) { 5296 udf_node->fe = &dscr->fe; 5297 fid_size = udf_create_new_fe(ump, udf_node->fe, 5298 udf_file_type, &udf_node->loc, 5299 &dir_node->loc, parent_unique_id); 5300 /* TODO add extended attribute for creation time */ 5301 } else { 5302 udf_node->efe = &dscr->efe; 5303 fid_size = udf_create_new_efe(ump, udf_node->efe, 5304 udf_file_type, &udf_node->loc, 5305 &dir_node->loc, parent_unique_id); 5306 } 5307 KASSERT(dscr->tag.tag_loc == udf_node->loc.loc.lb_num); 5308 5309 /* update vnode's size and type */ 5310 nvp->v_type = vap->va_type; 5311 uvm_vnp_setsize(nvp, fid_size); 5312 5313 /* set access mode */ 5314 udf_setaccessmode(udf_node, vap->va_mode); 5315 5316 /* set ownership */ 5317 uid = kauth_cred_geteuid(cnp->cn_cred); 5318 gid = parent_gid; 5319 udf_setownership(udf_node, uid, gid); 5320 5321 error = udf_dir_attach(ump, dir_node, udf_node, vap, cnp); 5322 if (error) { 5323 /* free disc allocation for node */ 5324 udf_free_allocated_space(ump, lb_num, vpart_num, 1); 5325 5326 /* recycle udf_node */ 5327 udf_dispose_node(udf_node); 5328 vput(nvp); 5329 5330 *vpp = NULL; 5331 return error; 5332 } 5333 5334 /* adjust file count */ 5335 udf_adjust_filecount(udf_node, 1); 5336 5337 /* return result */ 5338 *vpp = nvp; 5339 5340 return 0; 5341 } 5342 5343 5344 int 5345 udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, 5346 struct componentname *cnp) 5347 { 5348 int (**vnodeops)(void *); 5349 int udf_file_type; 5350 5351 DPRINTF(NODE, ("udf_create_node called\n")); 5352 5353 /* what type are we creating ? */ 5354 vnodeops = udf_vnodeop_p; 5355 /* start with a default */ 5356 udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS; 5357 5358 *vpp = NULL; 5359 5360 switch (vap->va_type) { 5361 case VREG : 5362 udf_file_type = UDF_ICB_FILETYPE_RANDOMACCESS; 5363 break; 5364 case VDIR : 5365 udf_file_type = UDF_ICB_FILETYPE_DIRECTORY; 5366 break; 5367 case VLNK : 5368 udf_file_type = UDF_ICB_FILETYPE_SYMLINK; 5369 break; 5370 case VBLK : 5371 udf_file_type = UDF_ICB_FILETYPE_BLOCKDEVICE; 5372 /* specfs */ 5373 return ENOTSUP; 5374 break; 5375 case VCHR : 5376 udf_file_type = UDF_ICB_FILETYPE_CHARDEVICE; 5377 /* specfs */ 5378 return ENOTSUP; 5379 break; 5380 case VFIFO : 5381 udf_file_type = UDF_ICB_FILETYPE_FIFO; 5382 /* specfs */ 5383 return ENOTSUP; 5384 break; 5385 case VSOCK : 5386 udf_file_type = UDF_ICB_FILETYPE_SOCKET; 5387 /* specfs */ 5388 return ENOTSUP; 5389 break; 5390 case VNON : 5391 case VBAD : 5392 default : 5393 /* nothing; can we even create these? */ 5394 return EINVAL; 5395 } 5396 5397 return udf_create_node_raw(dvp, vpp, udf_file_type, vnodeops, vap, cnp); 5398 } 5399 5400 /* --------------------------------------------------------------------- */ 5401 5402 static void 5403 udf_free_descriptor_space(struct udf_node *udf_node, struct long_ad *loc, void *mem) 5404 { 5405 struct udf_mount *ump = udf_node->ump; 5406 uint32_t lb_size, lb_num, len, num_lb; 5407 uint16_t vpart_num; 5408 5409 /* is there really one? */ 5410 if (mem == NULL) 5411 return; 5412 5413 /* got a descriptor here */ 5414 len = UDF_EXT_LEN(udf_rw32(loc->len)); 5415 lb_num = udf_rw32(loc->loc.lb_num); 5416 vpart_num = udf_rw16(loc->loc.part_num); 5417 5418 lb_size = udf_rw32(ump->logical_vol->lb_size); 5419 num_lb = (len + lb_size -1) / lb_size; 5420 5421 udf_free_allocated_space(ump, lb_num, vpart_num, num_lb); 5422 } 5423 5424 void 5425 udf_delete_node(struct udf_node *udf_node) 5426 { 5427 void *dscr; 5428 struct udf_mount *ump; 5429 struct long_ad *loc; 5430 int extnr, lvint, dummy; 5431 5432 ump = udf_node->ump; 5433 5434 /* paranoia check on integrity; should be open!; we could panic */ 5435 lvint = udf_rw32(udf_node->ump->logvol_integrity->integrity_type); 5436 if (lvint == UDF_INTEGRITY_CLOSED) 5437 printf("\tIntegrity was CLOSED!\n"); 5438 5439 /* whatever the node type, change its size to zero */ 5440 (void) udf_resize_node(udf_node, 0, &dummy); 5441 5442 /* force it to be `clean'; no use writing it out */ 5443 udf_node->i_flags &= ~(IN_MODIFIED | IN_ACCESSED | IN_ACCESS | 5444 IN_CHANGE | IN_UPDATE | IN_MODIFY); 5445 5446 /* adjust file count */ 5447 udf_adjust_filecount(udf_node, -1); 5448 5449 /* 5450 * Free its allocated descriptors; memory will be released when 5451 * vop_reclaim() is called. 5452 */ 5453 loc = &udf_node->loc; 5454 5455 dscr = udf_node->fe; 5456 udf_free_descriptor_space(udf_node, loc, dscr); 5457 dscr = udf_node->efe; 5458 udf_free_descriptor_space(udf_node, loc, dscr); 5459 5460 for (extnr = 0; extnr < UDF_MAX_ALLOC_EXTENTS; extnr++) { 5461 dscr = udf_node->ext[extnr]; 5462 loc = &udf_node->ext_loc[extnr]; 5463 udf_free_descriptor_space(udf_node, loc, dscr); 5464 } 5465 } 5466 5467 /* --------------------------------------------------------------------- */ 5468 5469 /* set new filesize; node but be LOCKED on entry and is locked on exit */ 5470 int 5471 udf_resize_node(struct udf_node *udf_node, uint64_t new_size, int *extended) 5472 { 5473 struct file_entry *fe = udf_node->fe; 5474 struct extfile_entry *efe = udf_node->efe; 5475 uint64_t file_size; 5476 int error; 5477 5478 if (fe) { 5479 file_size = udf_rw64(fe->inf_len); 5480 } else { 5481 assert(udf_node->efe); 5482 file_size = udf_rw64(efe->inf_len); 5483 } 5484 5485 DPRINTF(ATTR, ("\tchanging file length from %"PRIu64" to %"PRIu64"\n", 5486 file_size, new_size)); 5487 5488 /* if not changing, we're done */ 5489 if (file_size == new_size) 5490 return 0; 5491 5492 *extended = (new_size > file_size); 5493 if (*extended) { 5494 error = udf_grow_node(udf_node, new_size); 5495 } else { 5496 error = udf_shrink_node(udf_node, new_size); 5497 } 5498 5499 return error; 5500 } 5501 5502 5503 /* --------------------------------------------------------------------- */ 5504 5505 void 5506 udf_itimes(struct udf_node *udf_node, struct timespec *acc, 5507 struct timespec *mod, struct timespec *birth) 5508 { 5509 struct timespec now; 5510 struct file_entry *fe; 5511 struct extfile_entry *efe; 5512 struct filetimes_extattr_entry *ft_extattr; 5513 struct timestamp *atime, *mtime, *attrtime, *ctime; 5514 struct timestamp fe_ctime; 5515 struct timespec cur_birth; 5516 uint32_t offset, a_l; 5517 uint8_t *filedata; 5518 int error; 5519 5520 /* protect against rogue values */ 5521 if (!udf_node) 5522 return; 5523 5524 fe = udf_node->fe; 5525 efe = udf_node->efe; 5526 5527 if (!(udf_node->i_flags & (IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_MODIFY))) 5528 return; 5529 5530 /* get descriptor information */ 5531 if (fe) { 5532 atime = &fe->atime; 5533 mtime = &fe->mtime; 5534 attrtime = &fe->attrtime; 5535 filedata = fe->data; 5536 5537 /* initial save dummy setting */ 5538 ctime = &fe_ctime; 5539 5540 /* check our extended attribute if present */ 5541 error = udf_extattr_search_intern(udf_node, 5542 UDF_FILETIMES_ATTR_NO, "", &offset, &a_l); 5543 if (!error) { 5544 ft_extattr = (struct filetimes_extattr_entry *) 5545 (filedata + offset); 5546 if (ft_extattr->existence & UDF_FILETIMES_FILE_CREATION) 5547 ctime = &ft_extattr->times[0]; 5548 } 5549 /* TODO create the extended attribute if not found ? */ 5550 } else { 5551 assert(udf_node->efe); 5552 atime = &efe->atime; 5553 mtime = &efe->mtime; 5554 attrtime = &efe->attrtime; 5555 ctime = &efe->ctime; 5556 } 5557 5558 vfs_timestamp(&now); 5559 5560 /* set access time */ 5561 if (udf_node->i_flags & IN_ACCESS) { 5562 if (acc == NULL) 5563 acc = &now; 5564 udf_timespec_to_timestamp(acc, atime); 5565 } 5566 5567 /* set modification time */ 5568 if (udf_node->i_flags & (IN_UPDATE | IN_MODIFY)) { 5569 if (mod == NULL) 5570 mod = &now; 5571 udf_timespec_to_timestamp(mod, mtime); 5572 5573 /* ensure birthtime is older than set modification! */ 5574 udf_timestamp_to_timespec(udf_node->ump, ctime, &cur_birth); 5575 if ((cur_birth.tv_sec > mod->tv_sec) || 5576 ((cur_birth.tv_sec == mod->tv_sec) && 5577 (cur_birth.tv_nsec > mod->tv_nsec))) { 5578 udf_timespec_to_timestamp(mod, ctime); 5579 } 5580 } 5581 5582 /* update birthtime if specified */ 5583 /* XXX we asume here that given birthtime is older than mod */ 5584 if (birth && (birth->tv_sec != VNOVAL)) { 5585 udf_timespec_to_timestamp(birth, ctime); 5586 } 5587 5588 /* set change time */ 5589 if (udf_node->i_flags & (IN_CHANGE | IN_MODIFY)) 5590 udf_timespec_to_timestamp(&now, attrtime); 5591 5592 /* notify updates to the node itself */ 5593 if (udf_node->i_flags & (IN_ACCESS | IN_MODIFY)) 5594 udf_node->i_flags |= IN_ACCESSED; 5595 if (udf_node->i_flags & (IN_UPDATE | IN_CHANGE)) 5596 udf_node->i_flags |= IN_MODIFIED; 5597 5598 /* clear modification flags */ 5599 udf_node->i_flags &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY); 5600 } 5601 5602 /* --------------------------------------------------------------------- */ 5603 5604 int 5605 udf_update(struct vnode *vp, struct timespec *acc, 5606 struct timespec *mod, struct timespec *birth, int updflags) 5607 { 5608 union dscrptr *dscrptr; 5609 struct udf_node *udf_node = VTOI(vp); 5610 struct udf_mount *ump = udf_node->ump; 5611 struct regid *impl_id; 5612 int mnt_async = (vp->v_mount->mnt_flag & MNT_ASYNC); 5613 int waitfor, flags; 5614 5615 #ifdef DEBUG 5616 char bits[128]; 5617 DPRINTF(CALL, ("udf_update(node, %p, %p, %p, %d)\n", acc, mod, birth, 5618 updflags)); 5619 bitmask_snprintf(udf_node->i_flags, IN_FLAGBITS, bits, sizeof(bits)); 5620 DPRINTF(CALL, ("\tnode flags %s\n", bits)); 5621 DPRINTF(CALL, ("\t\tmnt_async = %d\n", mnt_async)); 5622 #endif 5623 5624 /* set our times */ 5625 udf_itimes(udf_node, acc, mod, birth); 5626 5627 /* set our implementation id */ 5628 if (udf_node->fe) { 5629 dscrptr = (union dscrptr *) udf_node->fe; 5630 impl_id = &udf_node->fe->imp_id; 5631 } else { 5632 dscrptr = (union dscrptr *) udf_node->efe; 5633 impl_id = &udf_node->efe->imp_id; 5634 } 5635 5636 /* set our ID */ 5637 udf_set_regid(impl_id, IMPL_NAME); 5638 udf_add_impl_regid(ump, impl_id); 5639 5640 /* update our crc! on RMW we are not allowed to change a thing */ 5641 udf_validate_tag_and_crc_sums(dscrptr); 5642 5643 /* if called when mounted readonly, never write back */ 5644 if (vp->v_mount->mnt_flag & MNT_RDONLY) 5645 return 0; 5646 5647 /* check if the node is dirty 'enough'*/ 5648 if (updflags & UPDATE_CLOSE) { 5649 flags = udf_node->i_flags & (IN_MODIFIED | IN_ACCESSED); 5650 } else { 5651 flags = udf_node->i_flags & IN_MODIFIED; 5652 } 5653 if (flags == 0) 5654 return 0; 5655 5656 /* determine if we need to write sync or async */ 5657 waitfor = 0; 5658 if ((flags & IN_MODIFIED) && (mnt_async == 0)) { 5659 /* sync mounted */ 5660 waitfor = updflags & UPDATE_WAIT; 5661 if (updflags & UPDATE_DIROP) 5662 waitfor |= UPDATE_WAIT; 5663 } 5664 if (waitfor) 5665 return VOP_FSYNC(vp, FSCRED, FSYNC_WAIT, 0,0); 5666 5667 return 0; 5668 } 5669 5670 5671 /* --------------------------------------------------------------------- */ 5672 5673 5674 /* 5675 * Read one fid and process it into a dirent and advance to the next (*fid) 5676 * has to be allocated a logical block in size, (*dirent) struct dirent length 5677 */ 5678 5679 int 5680 udf_read_fid_stream(struct vnode *vp, uint64_t *offset, 5681 struct fileid_desc *fid, struct dirent *dirent) 5682 { 5683 struct udf_node *dir_node = VTOI(vp); 5684 struct udf_mount *ump = dir_node->ump; 5685 struct file_entry *fe = dir_node->fe; 5686 struct extfile_entry *efe = dir_node->efe; 5687 uint32_t fid_size, lb_size; 5688 uint64_t file_size; 5689 char *fid_name; 5690 int enough, error; 5691 5692 assert(fid); 5693 assert(dirent); 5694 assert(dir_node); 5695 assert(offset); 5696 assert(*offset != 1); 5697 5698 DPRINTF(FIDS, ("read_fid_stream called at offset %"PRIu64"\n", *offset)); 5699 /* check if we're past the end of the directory */ 5700 if (fe) { 5701 file_size = udf_rw64(fe->inf_len); 5702 } else { 5703 assert(dir_node->efe); 5704 file_size = udf_rw64(efe->inf_len); 5705 } 5706 if (*offset >= file_size) 5707 return EINVAL; 5708 5709 /* get maximum length of FID descriptor */ 5710 lb_size = udf_rw32(ump->logical_vol->lb_size); 5711 5712 /* initialise return values */ 5713 fid_size = 0; 5714 memset(dirent, 0, sizeof(struct dirent)); 5715 memset(fid, 0, lb_size); 5716 5717 enough = (file_size - (*offset) >= UDF_FID_SIZE); 5718 if (!enough) { 5719 /* short dir ... */ 5720 return EIO; 5721 } 5722 5723 error = vn_rdwr(UIO_READ, vp, 5724 fid, MIN(file_size - (*offset), lb_size), *offset, 5725 UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, FSCRED, 5726 NULL, NULL); 5727 if (error) 5728 return error; 5729 5730 DPRINTF(FIDS, ("\tfid piece read in fine\n")); 5731 /* 5732 * Check if we got a whole descriptor. 5733 * TODO Try to `resync' directory stream when something is very wrong. 5734 */ 5735 5736 /* check if our FID header is OK */ 5737 error = udf_check_tag(fid); 5738 if (error) { 5739 goto brokendir; 5740 } 5741 DPRINTF(FIDS, ("\ttag check ok\n")); 5742 5743 if (udf_rw16(fid->tag.id) != TAGID_FID) { 5744 error = EIO; 5745 goto brokendir; 5746 } 5747 DPRINTF(FIDS, ("\ttag checked ok: got TAGID_FID\n")); 5748 5749 /* check for length */ 5750 fid_size = udf_fidsize(fid); 5751 enough = (file_size - (*offset) >= fid_size); 5752 if (!enough) { 5753 error = EIO; 5754 goto brokendir; 5755 } 5756 DPRINTF(FIDS, ("\tthe complete fid is read in\n")); 5757 5758 /* check FID contents */ 5759 error = udf_check_tag_payload((union dscrptr *) fid, lb_size); 5760 brokendir: 5761 if (error) { 5762 /* note that is sometimes a bit quick to report */ 5763 printf("BROKEN DIRECTORY ENTRY\n"); 5764 /* RESYNC? */ 5765 /* TODO: use udf_resync_fid_stream */ 5766 return EIO; 5767 } 5768 DPRINTF(FIDS, ("\tpayload checked ok\n")); 5769 5770 /* we got a whole and valid descriptor! */ 5771 DPRINTF(FIDS, ("\tinterpret FID\n")); 5772 5773 /* create resulting dirent structure */ 5774 fid_name = (char *) fid->data + udf_rw16(fid->l_iu); 5775 udf_to_unix_name(dirent->d_name, MAXNAMLEN, 5776 fid_name, fid->l_fi, &ump->logical_vol->desc_charset); 5777 5778 /* '..' has no name, so provide one */ 5779 if (fid->file_char & UDF_FILE_CHAR_PAR) 5780 strcpy(dirent->d_name, ".."); 5781 5782 dirent->d_fileno = udf_calchash(&fid->icb); /* inode hash XXX */ 5783 dirent->d_namlen = strlen(dirent->d_name); 5784 dirent->d_reclen = _DIRENT_SIZE(dirent); 5785 5786 /* 5787 * Note that its not worth trying to go for the filetypes now... its 5788 * too expensive too 5789 */ 5790 dirent->d_type = DT_UNKNOWN; 5791 5792 /* initial guess for filetype we can make */ 5793 if (fid->file_char & UDF_FILE_CHAR_DIR) 5794 dirent->d_type = DT_DIR; 5795 5796 /* advance */ 5797 *offset += fid_size; 5798 5799 return error; 5800 } 5801 5802 5803 /* --------------------------------------------------------------------- */ 5804 5805 static void 5806 udf_sync_pass(struct udf_mount *ump, kauth_cred_t cred, int waitfor, 5807 int pass, int *ndirty) 5808 { 5809 struct udf_node *udf_node, *n_udf_node; 5810 struct vnode *vp; 5811 int vdirty, error; 5812 int on_type, on_flags, on_vnode; 5813 5814 derailed: 5815 KASSERT(mutex_owned(&mntvnode_lock)); 5816 5817 DPRINTF(SYNC, ("sync_pass %d\n", pass)); 5818 udf_node = LIST_FIRST(&ump->sorted_udf_nodes); 5819 for (;udf_node; udf_node = n_udf_node) { 5820 DPRINTF(SYNC, (".")); 5821 5822 udf_node->i_flags &= ~IN_SYNCED; 5823 vp = udf_node->vnode; 5824 5825 mutex_enter(&vp->v_interlock); 5826 n_udf_node = LIST_NEXT(udf_node, sortchain); 5827 if (n_udf_node) 5828 n_udf_node->i_flags |= IN_SYNCED; 5829 5830 /* system nodes are not synced this way */ 5831 if (vp->v_vflag & VV_SYSTEM) { 5832 mutex_exit(&vp->v_interlock); 5833 continue; 5834 } 5835 5836 /* check if its dirty enough to even try */ 5837 on_type = (waitfor == MNT_LAZY || vp->v_type == VNON); 5838 on_flags = ((udf_node->i_flags & 5839 (IN_ACCESSED | IN_UPDATE | IN_MODIFIED)) == 0); 5840 on_vnode = LIST_EMPTY(&vp->v_dirtyblkhd) 5841 && UVM_OBJ_IS_CLEAN(&vp->v_uobj); 5842 if (on_type || (on_flags || on_vnode)) { /* XXX */ 5843 /* not dirty (enough?) */ 5844 mutex_exit(&vp->v_interlock); 5845 continue; 5846 } 5847 5848 mutex_exit(&mntvnode_lock); 5849 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK); 5850 if (error) { 5851 mutex_enter(&mntvnode_lock); 5852 if (error == ENOENT) 5853 goto derailed; 5854 *ndirty += 1; 5855 continue; 5856 } 5857 5858 switch (pass) { 5859 case 1: 5860 VOP_FSYNC(vp, cred, 0 | FSYNC_DATAONLY,0,0); 5861 break; 5862 case 2: 5863 vdirty = vp->v_numoutput; 5864 if (vp->v_tag == VT_UDF) 5865 vdirty += udf_node->outstanding_bufs + 5866 udf_node->outstanding_nodedscr; 5867 if (vdirty == 0) 5868 VOP_FSYNC(vp, cred, 0,0,0); 5869 *ndirty += vdirty; 5870 break; 5871 case 3: 5872 vdirty = vp->v_numoutput; 5873 if (vp->v_tag == VT_UDF) 5874 vdirty += udf_node->outstanding_bufs + 5875 udf_node->outstanding_nodedscr; 5876 *ndirty += vdirty; 5877 break; 5878 } 5879 5880 vput(vp); 5881 mutex_enter(&mntvnode_lock); 5882 } 5883 DPRINTF(SYNC, ("END sync_pass %d\n", pass)); 5884 } 5885 5886 5887 void 5888 udf_do_sync(struct udf_mount *ump, kauth_cred_t cred, int waitfor) 5889 { 5890 int dummy, ndirty; 5891 5892 mutex_enter(&mntvnode_lock); 5893 recount: 5894 dummy = 0; 5895 DPRINTF(CALL, ("issue VOP_FSYNC(DATA only) on all nodes\n")); 5896 DPRINTF(SYNC, ("issue VOP_FSYNC(DATA only) on all nodes\n")); 5897 udf_sync_pass(ump, cred, waitfor, 1, &dummy); 5898 5899 DPRINTF(CALL, ("issue VOP_FSYNC(COMPLETE) on all finished nodes\n")); 5900 DPRINTF(SYNC, ("issue VOP_FSYNC(COMPLETE) on all finished nodes\n")); 5901 udf_sync_pass(ump, cred, waitfor, 2, &dummy); 5902 5903 if (waitfor == MNT_WAIT) { 5904 ndirty = ump->devvp->v_numoutput; 5905 DPRINTF(NODE, ("counting pending blocks: on devvp %d\n", 5906 ndirty)); 5907 udf_sync_pass(ump, cred, waitfor, 3, &ndirty); 5908 DPRINTF(NODE, ("counted num dirty pending blocks %d\n", 5909 ndirty)); 5910 5911 if (ndirty) { 5912 /* 1/4 second wait */ 5913 cv_timedwait(&ump->dirtynodes_cv, &mntvnode_lock, 5914 hz/4); 5915 goto recount; 5916 } 5917 } 5918 5919 mutex_exit(&mntvnode_lock); 5920 } 5921 5922 /* --------------------------------------------------------------------- */ 5923 5924 /* 5925 * Read and write file extent in/from the buffer. 5926 * 5927 * The splitup of the extent into seperate request-buffers is to minimise 5928 * copying around as much as possible. 5929 * 5930 * block based file reading and writing 5931 */ 5932 5933 static int 5934 udf_read_internal(struct udf_node *node, uint8_t *blob) 5935 { 5936 struct udf_mount *ump; 5937 struct file_entry *fe = node->fe; 5938 struct extfile_entry *efe = node->efe; 5939 uint64_t inflen; 5940 uint32_t sector_size; 5941 uint8_t *pos; 5942 int icbflags, addr_type; 5943 5944 /* get extent and do some paranoia checks */ 5945 ump = node->ump; 5946 sector_size = ump->discinfo.sector_size; 5947 5948 if (fe) { 5949 inflen = udf_rw64(fe->inf_len); 5950 pos = &fe->data[0] + udf_rw32(fe->l_ea); 5951 icbflags = udf_rw16(fe->icbtag.flags); 5952 } else { 5953 assert(node->efe); 5954 inflen = udf_rw64(efe->inf_len); 5955 pos = &efe->data[0] + udf_rw32(efe->l_ea); 5956 icbflags = udf_rw16(efe->icbtag.flags); 5957 } 5958 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 5959 5960 assert(addr_type == UDF_ICB_INTERN_ALLOC); 5961 assert(inflen < sector_size); 5962 5963 /* copy out info */ 5964 memset(blob, 0, sector_size); 5965 memcpy(blob, pos, inflen); 5966 5967 return 0; 5968 } 5969 5970 5971 static int 5972 udf_write_internal(struct udf_node *node, uint8_t *blob) 5973 { 5974 struct udf_mount *ump; 5975 struct file_entry *fe = node->fe; 5976 struct extfile_entry *efe = node->efe; 5977 uint64_t inflen; 5978 uint32_t sector_size; 5979 uint8_t *pos; 5980 int icbflags, addr_type; 5981 5982 /* get extent and do some paranoia checks */ 5983 ump = node->ump; 5984 sector_size = ump->discinfo.sector_size; 5985 5986 if (fe) { 5987 inflen = udf_rw64(fe->inf_len); 5988 pos = &fe->data[0] + udf_rw32(fe->l_ea); 5989 icbflags = udf_rw16(fe->icbtag.flags); 5990 } else { 5991 assert(node->efe); 5992 inflen = udf_rw64(efe->inf_len); 5993 pos = &efe->data[0] + udf_rw32(efe->l_ea); 5994 icbflags = udf_rw16(efe->icbtag.flags); 5995 } 5996 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 5997 5998 assert(addr_type == UDF_ICB_INTERN_ALLOC); 5999 assert(inflen < sector_size); 6000 6001 /* copy in blob */ 6002 /* memset(pos, 0, inflen); */ 6003 memcpy(pos, blob, inflen); 6004 6005 return 0; 6006 } 6007 6008 6009 void 6010 udf_read_filebuf(struct udf_node *udf_node, struct buf *buf) 6011 { 6012 struct buf *nestbuf; 6013 struct udf_mount *ump = udf_node->ump; 6014 uint64_t *mapping; 6015 uint64_t run_start; 6016 uint32_t sector_size; 6017 uint32_t buf_offset, sector, rbuflen, rblk; 6018 uint32_t from, lblkno; 6019 uint32_t sectors; 6020 uint8_t *buf_pos; 6021 int error, run_length, isdir, what; 6022 6023 sector_size = udf_node->ump->discinfo.sector_size; 6024 6025 from = buf->b_blkno; 6026 sectors = buf->b_bcount / sector_size; 6027 6028 isdir = (udf_node->vnode->v_type == VDIR); 6029 what = isdir ? UDF_C_FIDS : UDF_C_USERDATA; 6030 6031 /* assure we have enough translation slots */ 6032 KASSERT(buf->b_bcount / sector_size <= UDF_MAX_MAPPINGS); 6033 KASSERT(MAXPHYS / sector_size <= UDF_MAX_MAPPINGS); 6034 6035 if (sectors > UDF_MAX_MAPPINGS) { 6036 printf("udf_read_filebuf: implementation limit on bufsize\n"); 6037 buf->b_error = EIO; 6038 biodone(buf); 6039 return; 6040 } 6041 6042 mapping = malloc(sizeof(*mapping) * UDF_MAX_MAPPINGS, M_TEMP, M_WAITOK); 6043 6044 error = 0; 6045 DPRINTF(READ, ("\ttranslate %d-%d\n", from, sectors)); 6046 error = udf_translate_file_extent(udf_node, from, sectors, mapping); 6047 if (error) { 6048 buf->b_error = error; 6049 biodone(buf); 6050 goto out; 6051 } 6052 DPRINTF(READ, ("\ttranslate extent went OK\n")); 6053 6054 /* pre-check if its an internal */ 6055 if (*mapping == UDF_TRANS_INTERN) { 6056 error = udf_read_internal(udf_node, (uint8_t *) buf->b_data); 6057 if (error) 6058 buf->b_error = error; 6059 biodone(buf); 6060 goto out; 6061 } 6062 DPRINTF(READ, ("\tnot intern\n")); 6063 6064 #ifdef DEBUG 6065 if (udf_verbose & UDF_DEBUG_TRANSLATE) { 6066 printf("Returned translation table:\n"); 6067 for (sector = 0; sector < sectors; sector++) { 6068 printf("%d : %"PRIu64"\n", sector, mapping[sector]); 6069 } 6070 } 6071 #endif 6072 6073 /* request read-in of data from disc sheduler */ 6074 buf->b_resid = buf->b_bcount; 6075 for (sector = 0; sector < sectors; sector++) { 6076 buf_offset = sector * sector_size; 6077 buf_pos = (uint8_t *) buf->b_data + buf_offset; 6078 DPRINTF(READ, ("\tprocessing rel sector %d\n", sector)); 6079 6080 /* check if its zero or unmapped to stop reading */ 6081 switch (mapping[sector]) { 6082 case UDF_TRANS_UNMAPPED: 6083 case UDF_TRANS_ZERO: 6084 /* copy zero sector TODO runlength like below */ 6085 memset(buf_pos, 0, sector_size); 6086 DPRINTF(READ, ("\treturning zero sector\n")); 6087 nestiobuf_done(buf, sector_size, 0); 6088 break; 6089 default : 6090 DPRINTF(READ, ("\tread sector " 6091 "%"PRIu64"\n", mapping[sector])); 6092 6093 lblkno = from + sector; 6094 run_start = mapping[sector]; 6095 run_length = 1; 6096 while (sector < sectors-1) { 6097 if (mapping[sector+1] != mapping[sector]+1) 6098 break; 6099 run_length++; 6100 sector++; 6101 } 6102 6103 /* 6104 * nest an iobuf and mark it for async reading. Since 6105 * we're using nested buffers, they can't be cached by 6106 * design. 6107 */ 6108 rbuflen = run_length * sector_size; 6109 rblk = run_start * (sector_size/DEV_BSIZE); 6110 6111 nestbuf = getiobuf(NULL, true); 6112 nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen); 6113 /* nestbuf is B_ASYNC */ 6114 6115 /* identify this nestbuf */ 6116 nestbuf->b_lblkno = lblkno; 6117 assert(nestbuf->b_vp == udf_node->vnode); 6118 6119 /* CD shedules on raw blkno */ 6120 nestbuf->b_blkno = rblk; 6121 nestbuf->b_proc = NULL; 6122 nestbuf->b_rawblkno = rblk; 6123 nestbuf->b_udf_c_type = what; 6124 6125 udf_discstrat_queuebuf(ump, nestbuf); 6126 } 6127 } 6128 out: 6129 /* if we're synchronously reading, wait for the completion */ 6130 if ((buf->b_flags & B_ASYNC) == 0) 6131 biowait(buf); 6132 6133 DPRINTF(READ, ("\tend of read_filebuf\n")); 6134 free(mapping, M_TEMP); 6135 return; 6136 } 6137 6138 6139 void 6140 udf_write_filebuf(struct udf_node *udf_node, struct buf *buf) 6141 { 6142 struct buf *nestbuf; 6143 struct udf_mount *ump = udf_node->ump; 6144 uint64_t *mapping; 6145 uint64_t run_start; 6146 uint32_t lb_size; 6147 uint32_t buf_offset, lb_num, rbuflen, rblk; 6148 uint32_t from, lblkno; 6149 uint32_t num_lb; 6150 uint8_t *buf_pos; 6151 int error, run_length, isdir, what, s; 6152 6153 lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); 6154 6155 from = buf->b_blkno; 6156 num_lb = buf->b_bcount / lb_size; 6157 6158 isdir = (udf_node->vnode->v_type == VDIR); 6159 what = isdir ? UDF_C_FIDS : UDF_C_USERDATA; 6160 6161 if (udf_node == ump->metadatabitmap_node) 6162 what = UDF_C_METADATA_SBM; 6163 6164 /* assure we have enough translation slots */ 6165 KASSERT(buf->b_bcount / lb_size <= UDF_MAX_MAPPINGS); 6166 KASSERT(MAXPHYS / lb_size <= UDF_MAX_MAPPINGS); 6167 6168 if (num_lb > UDF_MAX_MAPPINGS) { 6169 printf("udf_write_filebuf: implementation limit on bufsize\n"); 6170 buf->b_error = EIO; 6171 biodone(buf); 6172 return; 6173 } 6174 6175 mapping = malloc(sizeof(*mapping) * UDF_MAX_MAPPINGS, M_TEMP, M_WAITOK); 6176 6177 error = 0; 6178 DPRINTF(WRITE, ("\ttranslate %d-%d\n", from, num_lb)); 6179 error = udf_translate_file_extent(udf_node, from, num_lb, mapping); 6180 if (error) { 6181 buf->b_error = error; 6182 biodone(buf); 6183 goto out; 6184 } 6185 DPRINTF(WRITE, ("\ttranslate extent went OK\n")); 6186 6187 /* if its internally mapped, we can write it in the descriptor itself */ 6188 if (*mapping == UDF_TRANS_INTERN) { 6189 /* TODO paranoia check if we ARE going to have enough space */ 6190 error = udf_write_internal(udf_node, (uint8_t *) buf->b_data); 6191 if (error) 6192 buf->b_error = error; 6193 biodone(buf); 6194 goto out; 6195 } 6196 DPRINTF(WRITE, ("\tnot intern\n")); 6197 6198 /* request write out of data to disc sheduler */ 6199 buf->b_resid = buf->b_bcount; 6200 for (lb_num = 0; lb_num < num_lb; lb_num++) { 6201 buf_offset = lb_num * lb_size; 6202 buf_pos = (uint8_t *) buf->b_data + buf_offset; 6203 DPRINTF(WRITE, ("\tprocessing rel lb_num %d\n", lb_num)); 6204 6205 /* 6206 * Mappings are not that important here. Just before we write 6207 * the lb_num we late-allocate them when needed and update the 6208 * mapping in the udf_node. 6209 */ 6210 6211 /* XXX why not ignore the mapping altogether ? */ 6212 /* TODO estimate here how much will be late-allocated */ 6213 DPRINTF(WRITE, ("\twrite lb_num " 6214 "%"PRIu64, mapping[lb_num])); 6215 6216 lblkno = from + lb_num; 6217 run_start = mapping[lb_num]; 6218 run_length = 1; 6219 while (lb_num < num_lb-1) { 6220 if (mapping[lb_num+1] != mapping[lb_num]+1) 6221 if (mapping[lb_num+1] != mapping[lb_num]) 6222 break; 6223 run_length++; 6224 lb_num++; 6225 } 6226 DPRINTF(WRITE, ("+ %d\n", run_length)); 6227 6228 /* nest an iobuf on the master buffer for the extent */ 6229 rbuflen = run_length * lb_size; 6230 rblk = run_start * (lb_size/DEV_BSIZE); 6231 6232 #if 0 6233 /* if its zero or unmapped, our blknr gets -1 for unmapped */ 6234 switch (mapping[lb_num]) { 6235 case UDF_TRANS_UNMAPPED: 6236 case UDF_TRANS_ZERO: 6237 rblk = -1; 6238 break; 6239 default: 6240 rblk = run_start * (lb_size/DEV_BSIZE); 6241 break; 6242 } 6243 #endif 6244 6245 nestbuf = getiobuf(NULL, true); 6246 nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen); 6247 /* nestbuf is B_ASYNC */ 6248 6249 /* identify this nestbuf */ 6250 nestbuf->b_lblkno = lblkno; 6251 KASSERT(nestbuf->b_vp == udf_node->vnode); 6252 6253 /* CD shedules on raw blkno */ 6254 nestbuf->b_blkno = rblk; 6255 nestbuf->b_proc = NULL; 6256 nestbuf->b_rawblkno = rblk; 6257 nestbuf->b_udf_c_type = what; 6258 6259 /* increment our outstanding bufs counter */ 6260 s = splbio(); 6261 udf_node->outstanding_bufs++; 6262 splx(s); 6263 6264 udf_discstrat_queuebuf(ump, nestbuf); 6265 } 6266 out: 6267 /* if we're synchronously writing, wait for the completion */ 6268 if ((buf->b_flags & B_ASYNC) == 0) 6269 biowait(buf); 6270 6271 DPRINTF(WRITE, ("\tend of write_filebuf\n")); 6272 free(mapping, M_TEMP); 6273 return; 6274 } 6275 6276 /* --------------------------------------------------------------------- */ 6277 6278 6279