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