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