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