1 /* $OpenBSD: udf_vfsops.c,v 1.54 2016/08/25 00:06:44 dlg Exp $ */ 2 3 /* 4 * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org> 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 AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: src/sys/fs/udf/udf_vfsops.c,v 1.25 2005/01/25 15:52:03 phk Exp $ 29 */ 30 31 /* 32 * Ported to OpenBSD by Pedro Martelletto in February 2005. 33 */ 34 35 /* 36 * Ok, here's how it goes. The UDF specs are pretty clear on how each data 37 * structure is made up, but not very clear on how they relate to each other. 38 * Here is the skinny... This demostrates a filesystem with one file in the 39 * root directory. Subdirectories are treated just as normal files, but they 40 * have File Id Descriptors of their children as their file data. As for the 41 * Anchor Volume Descriptor Pointer, it can exist in two of the following three 42 * places: sector 256, sector n (the max sector of the disk), or sector 43 * n - 256. It's a pretty good bet that one will exist at sector 256 though. 44 * One caveat is unclosed CD media. For that, sector 256 cannot be written, 45 * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the 46 * media is closed. 47 */ 48 49 #include <sys/types.h> 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/uio.h> 53 #include <sys/buf.h> 54 #include <sys/dirent.h> 55 #include <sys/fcntl.h> 56 #include <sys/kernel.h> 57 #include <sys/malloc.h> 58 #include <sys/mutex.h> 59 #include <sys/mount.h> 60 #include <sys/namei.h> 61 #include <sys/pool.h> 62 #include <sys/proc.h> 63 #include <sys/lock.h> 64 #include <sys/queue.h> 65 #include <sys/vnode.h> 66 #include <sys/lock.h> 67 #include <sys/endian.h> 68 #include <sys/specdev.h> 69 70 #include <crypto/siphash.h> 71 72 #include <isofs/udf/ecma167-udf.h> 73 #include <isofs/udf/udf.h> 74 #include <isofs/udf/udf_extern.h> 75 76 struct pool udf_trans_pool; 77 struct pool unode_pool; 78 struct pool udf_ds_pool; 79 80 int udf_find_partmaps(struct umount *, struct logvol_desc *); 81 int udf_get_vpartmap(struct umount *, struct part_map_virt *); 82 int udf_get_spartmap(struct umount *, struct part_map_spare *); 83 int udf_get_mpartmap(struct umount *, struct part_map_meta *); 84 int udf_mountfs(struct vnode *, struct mount *, uint32_t, struct proc *); 85 86 const struct vfsops udf_vfsops = { 87 .vfs_fhtovp = udf_fhtovp, 88 .vfs_init = udf_init, 89 .vfs_mount = udf_mount, 90 .vfs_start = udf_start, 91 .vfs_root = udf_root, 92 .vfs_quotactl = udf_quotactl, 93 .vfs_statfs = udf_statfs, 94 .vfs_sync = udf_sync, 95 .vfs_unmount = udf_unmount, 96 .vfs_vget = udf_vget, 97 .vfs_vptofh = udf_vptofh, 98 .vfs_sysctl = udf_sysctl, 99 .vfs_checkexp = udf_checkexp, 100 }; 101 102 int 103 udf_init(struct vfsconf *foo) 104 { 105 pool_init(&udf_trans_pool, MAXNAMLEN * sizeof(unicode_t), 0, 0, 106 PR_WAITOK, "udftrpl", NULL); 107 pool_setipl(&udf_trans_pool, IPL_NONE); 108 pool_init(&unode_pool, sizeof(struct unode), 0, 0, 109 PR_WAITOK, "udfndpl", NULL); 110 pool_setipl(&unode_pool, IPL_NONE); 111 pool_init(&udf_ds_pool, sizeof(struct udf_dirstream), 0, 0, 112 PR_WAITOK, "udfdspl", NULL); 113 pool_setipl(&udf_ds_pool, IPL_NONE); 114 115 return (0); 116 } 117 118 int 119 udf_start(struct mount *mp, int flags, struct proc *p) 120 { 121 return (0); 122 } 123 124 int 125 udf_mount(struct mount *mp, const char *path, void *data, 126 struct nameidata *ndp, struct proc *p) 127 { 128 struct vnode *devvp; /* vnode of the mount device */ 129 struct udf_args args; 130 char fspec[MNAMELEN]; 131 int error; 132 133 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 134 mp->mnt_flag |= MNT_RDONLY; 135 #ifdef UDF_DEBUG 136 printf("udf_mount: enforcing read-only mode\n"); 137 #endif 138 } 139 140 /* 141 * No root filesystem support. Probably not a big deal, since the 142 * bootloader doesn't understand UDF. 143 */ 144 if (mp->mnt_flag & MNT_ROOTFS) 145 return (EOPNOTSUPP); 146 147 error = copyin(data, &args, sizeof(struct udf_args)); 148 if (error) 149 return (error); 150 151 if (args.fspec == NULL) 152 return (EINVAL); 153 154 error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL); 155 if (error) 156 return (error); 157 158 NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p); 159 if ((error = namei(ndp))) 160 return (error); 161 162 devvp = ndp->ni_vp; 163 if (devvp->v_type != VBLK) { 164 vrele(devvp); 165 return (ENOTBLK); 166 } 167 168 if (major(devvp->v_rdev) >= nblkdev) { 169 vrele(devvp); 170 return (ENXIO); 171 } 172 173 /* Check the access rights on the mount device */ 174 if (p->p_ucred->cr_uid) { 175 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 176 error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p); 177 VOP_UNLOCK(devvp, p); 178 if (error) { 179 vrele(devvp); 180 return (error); 181 } 182 } 183 184 if ((error = udf_mountfs(devvp, mp, args.lastblock, p))) { 185 vrele(devvp); 186 return (error); 187 } 188 189 /* 190 * Keep a copy of the mount information. 191 */ 192 bzero(mp->mnt_stat.f_mntonname, MNAMELEN); 193 strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN); 194 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 195 strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN); 196 bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN); 197 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); 198 199 return (0); 200 }; 201 202 /* 203 * Check the descriptor tag for both the correct id and correct checksum. 204 * Return zero if all is good, EINVAL if not. 205 */ 206 int 207 udf_checktag(struct desc_tag *tag, uint16_t id) 208 { 209 uint8_t *itag; 210 uint8_t i, cksum = 0; 211 212 itag = (uint8_t *)tag; 213 214 if (letoh16(tag->id) != id) 215 return (EINVAL); 216 217 for (i = 0; i < 15; i++) 218 cksum = cksum + itag[i]; 219 cksum = cksum - itag[4]; 220 221 if (cksum == tag->cksum) 222 return (0); 223 224 return (EINVAL); 225 } 226 227 int 228 udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p) 229 { 230 struct buf *bp = NULL; 231 struct anchor_vdp avdp; 232 struct umount *ump = NULL; 233 struct part_desc *pd; 234 struct logvol_desc *lvd; 235 struct fileset_desc *fsd; 236 struct extfile_entry *xfentry; 237 struct file_entry *fentry; 238 uint32_t sector, size, mvds_start, mvds_end; 239 uint32_t fsd_offset = 0; 240 uint16_t part_num = 0, fsd_part = 0; 241 int error = EINVAL; 242 int logvol_found = 0, part_found = 0, fsd_found = 0; 243 int bsize; 244 245 /* 246 * Disallow multiple mounts of the same device. 247 * Disallow mounting of a device that is currently in use 248 * (except for root, which might share swap device for miniroot). 249 * Flush out any old buffers remaining from a previous use. 250 */ 251 if ((error = vfs_mountedon(devvp))) 252 return (error); 253 if (vcount(devvp) > 1 && devvp != rootvp) 254 return (EBUSY); 255 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 256 error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0); 257 VOP_UNLOCK(devvp, p); 258 if (error) 259 return (error); 260 261 error = VOP_OPEN(devvp, FREAD, FSCRED, p); 262 if (error) 263 return (error); 264 265 ump = malloc(sizeof(*ump), M_UDFMOUNT, M_WAITOK | M_ZERO); 266 267 mp->mnt_data = ump; 268 mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev; 269 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 270 mp->mnt_stat.f_namemax = NAME_MAX; 271 mp->mnt_flag |= MNT_LOCAL; 272 273 ump->um_mountp = mp; 274 ump->um_dev = devvp->v_rdev; 275 ump->um_devvp = devvp; 276 277 bsize = 2048; /* Should probe the media for its size. */ 278 279 /* 280 * Get the Anchor Volume Descriptor Pointer from sector 256. 281 * Should also check sector n - 256, n, and 512. 282 */ 283 sector = 256; 284 if ((error = bread(devvp, sector * btodb(bsize), bsize, &bp)) != 0) 285 goto bail; 286 if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR))) 287 goto bail; 288 289 bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp)); 290 brelse(bp); 291 bp = NULL; 292 293 /* 294 * Extract the Partition Descriptor and Logical Volume Descriptor 295 * from the Volume Descriptor Sequence. 296 * Should we care about the partition type right now? 297 * What about multiple partitions? 298 */ 299 mvds_start = letoh32(avdp.main_vds_ex.loc); 300 mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize; 301 for (sector = mvds_start; sector < mvds_end; sector++) { 302 if ((error = bread(devvp, sector * btodb(bsize), bsize, 303 &bp)) != 0) { 304 printf("Can't read sector %d of VDS\n", sector); 305 goto bail; 306 } 307 lvd = (struct logvol_desc *)bp->b_data; 308 if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) { 309 ump->um_bsize = letoh32(lvd->lb_size); 310 ump->um_bmask = ump->um_bsize - 1; 311 ump->um_bshift = ffs(ump->um_bsize) - 1; 312 fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num); 313 fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num); 314 if (udf_find_partmaps(ump, lvd)) 315 break; 316 logvol_found = 1; 317 } 318 pd = (struct part_desc *)bp->b_data; 319 if (!udf_checktag(&pd->tag, TAGID_PARTITION)) { 320 part_found = 1; 321 part_num = letoh16(pd->part_num); 322 ump->um_len = ump->um_reallen = letoh32(pd->part_len); 323 ump->um_start = ump->um_realstart = letoh32(pd->start_loc); 324 } 325 326 brelse(bp); 327 bp = NULL; 328 if ((part_found) && (logvol_found)) 329 break; 330 } 331 332 if (!part_found || !logvol_found) { 333 error = EINVAL; 334 goto bail; 335 } 336 337 if (ISSET(ump->um_flags, UDF_MNT_USES_META)) { 338 /* Read Metadata File 'File Entry' to find Metadata file. */ 339 struct long_ad *la; 340 sector = ump->um_start + ump->um_meta_start; /* Set in udf_get_mpartmap() */ 341 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) { 342 printf("Cannot read sector %d for Metadata File Entry\n", sector); 343 error = EINVAL; 344 goto bail; 345 } 346 xfentry = (struct extfile_entry *)bp->b_data; 347 fentry = (struct file_entry *)bp->b_data; 348 if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0) 349 la = (struct long_ad *)&xfentry->data[letoh32(xfentry->l_ea)]; 350 else if (udf_checktag(&fentry->tag, TAGID_FENTRY) == 0) 351 la = (struct long_ad *)&fentry->data[letoh32(fentry->l_ea)]; 352 else { 353 printf("Invalid Metadata File FE @ sector %d! (tag.id %d)\n", 354 sector, fentry->tag.id); 355 error = EINVAL; 356 goto bail; 357 } 358 ump->um_meta_start = letoh32(la->loc.lb_num); 359 ump->um_meta_len = letoh32(la->len); 360 if (bp != NULL) { 361 brelse(bp); 362 bp = NULL; 363 } 364 } else if (fsd_part != part_num) { 365 printf("FSD does not lie within the partition!\n"); 366 error = EINVAL; 367 goto bail; 368 } 369 370 mtx_init(&ump->um_hashmtx, IPL_NONE); 371 ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK, 372 &ump->um_hashsz); 373 arc4random_buf(&ump->um_hashkey, sizeof(ump->um_hashkey)); 374 375 /* Get the VAT, if needed */ 376 if (ump->um_flags & UDF_MNT_FIND_VAT) { 377 error = udf_vat_get(ump, lb); 378 if (error) 379 goto bail; 380 } 381 382 /* 383 * Grab the Fileset Descriptor 384 * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing 385 * me in the right direction here. 386 */ 387 388 if (ISSET(ump->um_flags, UDF_MNT_USES_META)) 389 sector = ump->um_meta_start; 390 else 391 sector = fsd_offset; 392 udf_vat_map(ump, §or); 393 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) { 394 printf("Cannot read sector %d of FSD\n", sector); 395 goto bail; 396 } 397 fsd = (struct fileset_desc *)bp->b_data; 398 if (!udf_checktag(&fsd->tag, TAGID_FSD)) { 399 fsd_found = 1; 400 bcopy(&fsd->rootdir_icb, &ump->um_root_icb, 401 sizeof(struct long_ad)); 402 if (ISSET(ump->um_flags, UDF_MNT_USES_META)) { 403 ump->um_root_icb.loc.lb_num += ump->um_meta_start; 404 ump->um_root_icb.loc.part_num = part_num; 405 } 406 } 407 408 brelse(bp); 409 bp = NULL; 410 411 if (!fsd_found) { 412 printf("Couldn't find the fsd\n"); 413 error = EINVAL; 414 goto bail; 415 } 416 417 /* 418 * Find the file entry for the root directory. 419 */ 420 sector = letoh32(ump->um_root_icb.loc.lb_num); 421 size = letoh32(ump->um_root_icb.len); 422 udf_vat_map(ump, §or); 423 if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) { 424 printf("Cannot read sector %d\n", sector); 425 goto bail; 426 } 427 428 xfentry = (struct extfile_entry *)bp->b_data; 429 fentry = (struct file_entry *)bp->b_data; 430 error = udf_checktag(&xfentry->tag, TAGID_EXTFENTRY); 431 if (error) { 432 error = udf_checktag(&fentry->tag, TAGID_FENTRY); 433 if (error) { 434 printf("Invalid root file entry!\n"); 435 goto bail; 436 } 437 } 438 439 brelse(bp); 440 bp = NULL; 441 442 devvp->v_specmountpoint = mp; 443 444 return (0); 445 446 bail: 447 if (ump->um_hashtbl != NULL) 448 free(ump->um_hashtbl, M_UDFMOUNT, 0); 449 450 if (ump != NULL) { 451 free(ump, M_UDFMOUNT, 0); 452 mp->mnt_data = NULL; 453 mp->mnt_flag &= ~MNT_LOCAL; 454 } 455 if (devvp->v_specinfo) 456 devvp->v_specmountpoint = NULL; 457 if (bp != NULL) 458 brelse(bp); 459 460 vn_lock(devvp, LK_EXCLUSIVE|LK_RETRY, p); 461 VOP_CLOSE(devvp, FREAD, FSCRED, p); 462 VOP_UNLOCK(devvp, p); 463 464 return (error); 465 } 466 467 int 468 udf_unmount(struct mount *mp, int mntflags, struct proc *p) 469 { 470 struct umount *ump; 471 struct vnode *devvp; 472 int error, flags = 0; 473 474 ump = VFSTOUDFFS(mp); 475 devvp = ump->um_devvp; 476 477 if (mntflags & MNT_FORCE) 478 flags |= FORCECLOSE; 479 480 if ((error = vflush(mp, NULL, flags))) 481 return (error); 482 483 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 484 vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, 0); 485 (void)VOP_CLOSE(devvp, FREAD, NOCRED, p); 486 VOP_UNLOCK(devvp, p); 487 488 devvp->v_specmountpoint = NULL; 489 vrele(devvp); 490 491 if (ump->um_flags & UDF_MNT_USES_VAT) 492 free(ump->um_vat, M_UDFMOUNT, 0); 493 494 if (ump->um_stbl != NULL) 495 free(ump->um_stbl, M_UDFMOUNT, 0); 496 497 if (ump->um_hashtbl != NULL) 498 free(ump->um_hashtbl, M_UDFMOUNT, 0); 499 500 free(ump, M_UDFMOUNT, 0); 501 502 mp->mnt_data = NULL; 503 mp->mnt_flag &= ~MNT_LOCAL; 504 505 return (0); 506 } 507 508 int 509 udf_root(struct mount *mp, struct vnode **vpp) 510 { 511 struct umount *ump; 512 struct vnode *vp; 513 udfino_t id; 514 int error; 515 516 ump = VFSTOUDFFS(mp); 517 518 id = udf_getid(&ump->um_root_icb); 519 520 error = udf_vget(mp, id, vpp); 521 if (error) 522 return (error); 523 524 vp = *vpp; 525 vp->v_flag |= VROOT; 526 527 return (0); 528 } 529 530 int 531 udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, 532 struct proc *p) 533 { 534 return (EOPNOTSUPP); 535 } 536 537 int 538 udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) 539 { 540 struct umount *ump; 541 542 ump = VFSTOUDFFS(mp); 543 544 sbp->f_bsize = ump->um_bsize; 545 sbp->f_iosize = ump->um_bsize; 546 sbp->f_blocks = ump->um_len; 547 sbp->f_bfree = 0; 548 sbp->f_bavail = 0; 549 sbp->f_files = 0; 550 sbp->f_ffree = 0; 551 sbp->f_favail = 0; 552 copy_statfs_info(sbp, mp); 553 554 return (0); 555 } 556 557 int 558 udf_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) 559 { 560 return (0); 561 } 562 563 int 564 udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp) 565 { 566 struct buf *bp; 567 struct vnode *devvp; 568 struct umount *ump; 569 struct proc *p; 570 struct vnode *vp, *nvp; 571 struct unode *up; 572 struct extfile_entry *xfe; 573 struct file_entry *fe; 574 uint32_t sector; 575 int error, size; 576 577 if (ino > (udfino_t)-1) 578 panic("udf_vget: alien ino_t %llu", (unsigned long long)ino); 579 580 p = curproc; 581 bp = NULL; 582 *vpp = NULL; 583 ump = VFSTOUDFFS(mp); 584 585 /* See if we already have this in the cache */ 586 if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0) 587 return (error); 588 if (*vpp != NULL) 589 return (0); 590 591 /* 592 * Allocate memory and check the tag id's before grabbing a new 593 * vnode, since it's hard to roll back if there is a problem. 594 */ 595 up = pool_get(&unode_pool, PR_WAITOK | PR_ZERO); 596 597 /* 598 * Copy in the file entry. Per the spec, the size can only be 1 block. 599 */ 600 sector = ino; 601 devvp = ump->um_devvp; 602 udf_vat_map(ump, §or); 603 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) { 604 printf("Cannot read sector %d\n", sector); 605 pool_put(&unode_pool, up); 606 if (bp != NULL) 607 brelse(bp); 608 return (error); 609 } 610 611 xfe = (struct extfile_entry *)bp->b_data; 612 fe = (struct file_entry *)bp->b_data; 613 error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY); 614 if (error == 0) { 615 size = letoh32(xfe->l_ea) + letoh32(xfe->l_ad); 616 } else { 617 error = udf_checktag(&fe->tag, TAGID_FENTRY); 618 if (error) { 619 printf("Invalid file entry!\n"); 620 pool_put(&unode_pool, up); 621 if (bp != NULL) 622 brelse(bp); 623 return (ENOMEM); 624 } else 625 size = letoh32(fe->l_ea) + letoh32(fe->l_ad); 626 } 627 628 /* Allocate max size of FE/XFE. */ 629 up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE, M_UDFFENTRY, M_NOWAIT | M_ZERO); 630 if (up->u_fentry == NULL) { 631 pool_put(&unode_pool, up); 632 if (bp != NULL) 633 brelse(bp); 634 return (ENOMEM); /* Cannot allocate file entry block */ 635 } 636 637 if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0) 638 bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE); 639 else 640 bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE); 641 642 brelse(bp); 643 bp = NULL; 644 645 if ((error = udf_allocv(mp, &vp, p))) { 646 free(up->u_fentry, M_UDFFENTRY, 0); 647 pool_put(&unode_pool, up); 648 return (error); /* Error from udf_allocv() */ 649 } 650 651 up->u_vnode = vp; 652 up->u_ino = ino; 653 up->u_devvp = ump->um_devvp; 654 up->u_dev = ump->um_dev; 655 up->u_ump = ump; 656 vp->v_data = up; 657 vref(ump->um_devvp); 658 659 rrw_init(&up->u_lock, "unode"); 660 661 /* 662 * udf_hashins() will lock the vnode for us. 663 */ 664 udf_hashins(up); 665 666 switch (up->u_fentry->icbtag.file_type) { 667 default: 668 printf("Unrecognized file type (%d)\n", vp->v_type); 669 vp->v_type = VREG; 670 break; 671 case UDF_ICB_FILETYPE_DIRECTORY: 672 vp->v_type = VDIR; 673 break; 674 case UDF_ICB_FILETYPE_BLOCKDEVICE: 675 vp->v_type = VBLK; 676 break; 677 case UDF_ICB_FILETYPE_CHARDEVICE: 678 vp->v_type = VCHR; 679 break; 680 case UDF_ICB_FILETYPE_FIFO: 681 vp->v_type = VFIFO; 682 break; 683 case UDF_ICB_FILETYPE_SOCKET: 684 vp->v_type = VSOCK; 685 break; 686 case UDF_ICB_FILETYPE_SYMLINK: 687 vp->v_type = VLNK; 688 break; 689 case UDF_ICB_FILETYPE_RANDOMACCESS: 690 case UDF_ICB_FILETYPE_REALTIME: 691 case UDF_ICB_FILETYPE_UNKNOWN: 692 vp->v_type = VREG; 693 break; 694 } 695 696 /* check if this is a vnode alias */ 697 if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL) { 698 printf("found a vnode alias\n"); 699 /* 700 * Discard unneeded vnode, but save its udf_node. 701 * Note that the lock is carried over in the udf_node 702 */ 703 nvp->v_data = vp->v_data; 704 vp->v_data = NULL; 705 vp->v_op = &spec_vops; 706 vrele(vp); 707 vgone(vp); 708 /* 709 * Reinitialize aliased inode. 710 */ 711 vp = nvp; 712 ump->um_devvp = vp; 713 } 714 715 *vpp = vp; 716 717 return (0); 718 } 719 720 struct ifid { 721 u_short ifid_len; 722 u_short ifid_pad; 723 int ifid_ino; 724 long ifid_start; 725 }; 726 727 int 728 udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) 729 { 730 struct ifid *ifhp; 731 struct vnode *nvp; 732 int error; 733 734 ifhp = (struct ifid *)fhp; 735 736 if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) { 737 *vpp = NULLVP; 738 return (error); 739 } 740 741 *vpp = nvp; 742 743 return (0); 744 } 745 746 int 747 udf_vptofh(struct vnode *vp, struct fid *fhp) 748 { 749 struct unode *up; 750 struct ifid *ifhp; 751 752 up = VTOU(vp); 753 ifhp = (struct ifid *)fhp; 754 ifhp->ifid_len = sizeof(struct ifid); 755 ifhp->ifid_ino = up->u_ino; 756 757 return (0); 758 } 759 760 int 761 udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 762 size_t newlen, struct proc *p) 763 { 764 return (EINVAL); 765 } 766 767 int 768 udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp, 769 struct ucred **credanonp) 770 { 771 return (EACCES); /* For the time being */ 772 } 773 774 /* Handle a virtual partition map */ 775 int 776 udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv) 777 { 778 ump->um_flags |= UDF_MNT_FIND_VAT; /* Should do more than this */ 779 return (0); 780 } 781 782 /* Handle a sparable partition map */ 783 int 784 udf_get_spartmap(struct umount *ump, struct part_map_spare *pms) 785 { 786 struct buf *bp; 787 int i, error; 788 789 ump->um_stbl = malloc(letoh32(pms->st_size), M_UDFMOUNT, M_NOWAIT); 790 if (ump->um_stbl == NULL) 791 return (ENOMEM); 792 793 bzero(ump->um_stbl, letoh32(pms->st_size)); 794 795 /* Calculate the number of sectors per packet */ 796 ump->um_psecs = letoh16(pms->packet_len) / ump->um_bsize; 797 798 error = udf_readlblks(ump, letoh32(pms->st_loc[0]), 799 letoh32(pms->st_size), &bp); 800 801 if (error) { 802 if (bp != NULL) 803 brelse(bp); 804 free(ump->um_stbl, M_UDFMOUNT, 0); 805 return (error); /* Failed to read sparing table */ 806 } 807 808 bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size)); 809 brelse(bp); 810 bp = NULL; 811 812 if (udf_checktag(&ump->um_stbl->tag, 0)) { 813 free(ump->um_stbl, M_UDFMOUNT, 0); 814 return (EINVAL); /* Invalid sparing table found */ 815 } 816 817 /* 818 * See how many valid entries there are here. The list is 819 * supposed to be sorted, 0xfffffff0 and higher are not valid. 820 */ 821 for (i = 0; i < letoh16(ump->um_stbl->rt_l); i++) { 822 ump->um_stbl_len = i; 823 if (letoh32(ump->um_stbl->entries[i].org) >= 0xfffffff0) 824 break; 825 } 826 827 return (0); 828 } 829 830 /* Handle a metadata partition map */ 831 int 832 udf_get_mpartmap(struct umount *ump, struct part_map_meta *pmm) 833 { 834 ump->um_flags |= UDF_MNT_USES_META; 835 ump->um_meta_start = pmm->meta_file_lbn; 836 return (0); 837 } 838 839 /* Scan the partition maps */ 840 int 841 udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd) 842 { 843 struct regid *pmap_id; 844 unsigned char regid_id[UDF_REGID_ID_SIZE + 1]; 845 int i, ptype, psize, error; 846 uint8_t *pmap = (uint8_t *) &lvd->maps[0]; 847 848 for (i = 0; i < letoh32(lvd->n_pm); i++) { 849 ptype = pmap[0]; 850 psize = pmap[1]; 851 852 if (ptype != 1 && ptype != 2) 853 return (EINVAL); /* Invalid partition map type */ 854 855 if (psize != sizeof(struct part_map_1) && 856 psize != sizeof(struct part_map_2)) 857 return (EINVAL); /* Invalid partition map size */ 858 859 if (ptype == 1) { 860 pmap += sizeof(struct part_map_1); 861 continue; 862 } 863 864 /* Type 2 map. Find out the details */ 865 pmap_id = (struct regid *) &pmap[4]; 866 regid_id[UDF_REGID_ID_SIZE] = '\0'; 867 bcopy(&pmap_id->id[0], ®id_id[0], UDF_REGID_ID_SIZE); 868 869 if (!bcmp(®id_id[0], "*UDF Virtual Partition", 870 UDF_REGID_ID_SIZE)) 871 error = udf_get_vpartmap(ump, 872 (struct part_map_virt *) pmap); 873 else if (!bcmp(®id_id[0], "*UDF Sparable Partition", 874 UDF_REGID_ID_SIZE)) 875 error = udf_get_spartmap(ump, 876 (struct part_map_spare *) pmap); 877 else if (!bcmp(®id_id[0], "*UDF Metadata Partition", 878 UDF_REGID_ID_SIZE)) 879 error = udf_get_mpartmap(ump, 880 (struct part_map_meta *) pmap); 881 else 882 return (EINVAL); /* Unsupported partition map */ 883 884 if (error) 885 return (error); /* Error getting partition */ 886 887 pmap += sizeof(struct part_map_2); 888 } 889 890 return (0); 891 } 892