Annotation of sys/isofs/udf/udf_vfsops.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: udf_vfsops.c,v 1.23 2006/08/07 15:50:42 pedro 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 <pedro@openbsd.org> 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:
! 69: #include <miscfs/specfs/specdev.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_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: size_t len;
! 126: int error;
! 127:
! 128: if ((mp->mnt_flag & MNT_RDONLY) == 0) {
! 129: mp->mnt_flag |= MNT_RDONLY;
! 130: printf("udf_mount: enforcing read-only mode\n");
! 131: }
! 132:
! 133: /*
! 134: * No root filesystem support. Probably not a big deal, since the
! 135: * bootloader doesn't understand UDF.
! 136: */
! 137: if (mp->mnt_flag & MNT_ROOTFS)
! 138: return (EOPNOTSUPP);
! 139:
! 140: error = copyin(data, &args, sizeof(struct udf_args));
! 141: if (error)
! 142: return (error);
! 143:
! 144: if (args.fspec == NULL)
! 145: return (EINVAL);
! 146:
! 147: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
! 148: if ((error = namei(ndp)))
! 149: return (error);
! 150:
! 151: devvp = ndp->ni_vp;
! 152: if (devvp->v_type != VBLK) {
! 153: vrele(devvp);
! 154: return (ENOTBLK);
! 155: }
! 156:
! 157: if (major(devvp->v_rdev) >= nblkdev) {
! 158: vrele(devvp);
! 159: return (ENXIO);
! 160: }
! 161:
! 162: /* Check the access rights on the mount device */
! 163: if (p->p_ucred->cr_uid) {
! 164: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
! 165: error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p);
! 166: VOP_UNLOCK(devvp, 0, p);
! 167: if (error) {
! 168: vrele(devvp);
! 169: return (error);
! 170: }
! 171: }
! 172:
! 173: if ((error = udf_mountfs(devvp, mp, args.lastblock, p))) {
! 174: vrele(devvp);
! 175: return (error);
! 176: }
! 177:
! 178: /*
! 179: * Keep a copy of the mount information.
! 180: */
! 181: copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &len);
! 182: bzero(mp->mnt_stat.f_mntonname + len, MNAMELEN - len);
! 183: copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &len);
! 184: bzero(mp->mnt_stat.f_mntfromname + len, MNAMELEN - len);
! 185:
! 186: return (0);
! 187: };
! 188:
! 189: /*
! 190: * Check the descriptor tag for both the correct id and correct checksum.
! 191: * Return zero if all is good, EINVAL if not.
! 192: */
! 193: int
! 194: udf_checktag(struct desc_tag *tag, uint16_t id)
! 195: {
! 196: uint8_t *itag;
! 197: uint8_t i, cksum = 0;
! 198:
! 199: itag = (uint8_t *)tag;
! 200:
! 201: if (letoh16(tag->id) != id)
! 202: return (EINVAL);
! 203:
! 204: for (i = 0; i < 15; i++)
! 205: cksum = cksum + itag[i];
! 206: cksum = cksum - itag[4];
! 207:
! 208: if (cksum == tag->cksum)
! 209: return (0);
! 210:
! 211: return (EINVAL);
! 212: }
! 213:
! 214: int
! 215: udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
! 216: {
! 217: struct buf *bp = NULL;
! 218: struct anchor_vdp avdp;
! 219: struct umount *ump = NULL;
! 220: struct part_desc *pd;
! 221: struct logvol_desc *lvd;
! 222: struct fileset_desc *fsd;
! 223: struct file_entry *root_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, p);
! 242: error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
! 243: VOP_UNLOCK(devvp, 0, p);
! 244: if (error)
! 245: return (error);
! 246:
! 247: error = VOP_OPEN(devvp, FREAD, FSCRED, p);
! 248: if (error)
! 249: return (error);
! 250:
! 251: MALLOC(ump, struct umount *, sizeof(struct umount), M_UDFMOUNT,
! 252: M_WAITOK);
! 253: bzero(ump, sizeof(struct umount));
! 254:
! 255: mp->mnt_data = (qaddr_t) ump;
! 256: mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
! 257: mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_UDF);
! 258: mp->mnt_flag |= MNT_LOCAL;
! 259:
! 260: ump->um_mountp = mp;
! 261: ump->um_dev = devvp->v_rdev;
! 262: ump->um_devvp = devvp;
! 263:
! 264: bsize = 2048; /* Should probe the media for its size. */
! 265:
! 266: /*
! 267: * Get the Anchor Volume Descriptor Pointer from sector 256.
! 268: * Should also check sector n - 256, n, and 512.
! 269: */
! 270: sector = 256;
! 271: if ((error = bread(devvp, sector * btodb(bsize), bsize, NOCRED,
! 272: &bp)) != 0)
! 273: goto bail;
! 274: if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
! 275: goto bail;
! 276:
! 277: bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
! 278: brelse(bp);
! 279: bp = NULL;
! 280:
! 281: /*
! 282: * Extract the Partition Descriptor and Logical Volume Descriptor
! 283: * from the Volume Descriptor Sequence.
! 284: * Should we care about the partition type right now?
! 285: * What about multiple partitions?
! 286: */
! 287: mvds_start = letoh32(avdp.main_vds_ex.loc);
! 288: mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
! 289: for (sector = mvds_start; sector < mvds_end; sector++) {
! 290: if ((error = bread(devvp, sector * btodb(bsize), bsize,
! 291: NOCRED, &bp)) != 0) {
! 292: printf("Can't read sector %d of VDS\n", sector);
! 293: goto bail;
! 294: }
! 295: lvd = (struct logvol_desc *)bp->b_data;
! 296: if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
! 297: ump->um_bsize = letoh32(lvd->lb_size);
! 298: ump->um_bmask = ump->um_bsize - 1;
! 299: ump->um_bshift = ffs(ump->um_bsize) - 1;
! 300: fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num);
! 301: fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num);
! 302: if (udf_find_partmaps(ump, lvd))
! 303: break;
! 304: logvol_found = 1;
! 305: }
! 306: pd = (struct part_desc *)bp->b_data;
! 307: if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
! 308: part_found = 1;
! 309: part_num = letoh16(pd->part_num);
! 310: ump->um_len = letoh32(pd->part_len);
! 311: ump->um_start = letoh32(pd->start_loc);
! 312: }
! 313:
! 314: brelse(bp);
! 315: bp = NULL;
! 316: if ((part_found) && (logvol_found))
! 317: break;
! 318: }
! 319:
! 320: if (!part_found || !logvol_found) {
! 321: error = EINVAL;
! 322: goto bail;
! 323: }
! 324:
! 325: if (fsd_part != part_num) {
! 326: printf("FSD does not lie within the partition!\n");
! 327: error = EINVAL;
! 328: goto bail;
! 329: }
! 330:
! 331: mtx_init(&ump->um_hashmtx, IPL_NONE);
! 332: ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK,
! 333: &ump->um_hashsz);
! 334:
! 335: /* Get the VAT, if needed */
! 336: if (ump->um_flags & UDF_MNT_FIND_VAT) {
! 337: error = udf_vat_get(ump, lb);
! 338: if (error)
! 339: goto bail;
! 340: }
! 341:
! 342: /*
! 343: * Grab the Fileset Descriptor
! 344: * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
! 345: * me in the right direction here.
! 346: */
! 347: sector = fsd_offset;
! 348: udf_vat_map(ump, §or);
! 349: if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
! 350: printf("Cannot read sector %d of FSD\n", sector);
! 351: goto bail;
! 352: }
! 353: fsd = (struct fileset_desc *)bp->b_data;
! 354: if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
! 355: fsd_found = 1;
! 356: bcopy(&fsd->rootdir_icb, &ump->um_root_icb,
! 357: sizeof(struct long_ad));
! 358: }
! 359:
! 360: brelse(bp);
! 361: bp = NULL;
! 362:
! 363: if (!fsd_found) {
! 364: printf("Couldn't find the fsd\n");
! 365: error = EINVAL;
! 366: goto bail;
! 367: }
! 368:
! 369: /*
! 370: * Find the file entry for the root directory.
! 371: */
! 372: sector = letoh32(ump->um_root_icb.loc.lb_num);
! 373: size = letoh32(ump->um_root_icb.len);
! 374: udf_vat_map(ump, §or);
! 375: if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) {
! 376: printf("Cannot read sector %d\n", sector);
! 377: goto bail;
! 378: }
! 379:
! 380: root_fentry = (struct file_entry *)bp->b_data;
! 381: if ((error = udf_checktag(&root_fentry->tag, TAGID_FENTRY))) {
! 382: printf("Invalid root file entry!\n");
! 383: goto bail;
! 384: }
! 385:
! 386: brelse(bp);
! 387: bp = NULL;
! 388:
! 389: devvp->v_specmountpoint = mp;
! 390:
! 391: return (0);
! 392:
! 393: bail:
! 394: if (ump->um_hashtbl != NULL)
! 395: free(ump->um_hashtbl, M_UDFMOUNT);
! 396:
! 397: if (ump != NULL) {
! 398: FREE(ump, M_UDFMOUNT);
! 399: mp->mnt_data = NULL;
! 400: mp->mnt_flag &= ~MNT_LOCAL;
! 401: }
! 402: if (bp != NULL)
! 403: brelse(bp);
! 404: VOP_CLOSE(devvp, FREAD, FSCRED, p);
! 405:
! 406: return (error);
! 407: }
! 408:
! 409: int
! 410: udf_unmount(struct mount *mp, int mntflags, struct proc *p)
! 411: {
! 412: struct umount *ump;
! 413: struct vnode *devvp;
! 414: int error, flags = 0;
! 415:
! 416: ump = VFSTOUDFFS(mp);
! 417: devvp = ump->um_devvp;
! 418:
! 419: if (mntflags & MNT_FORCE)
! 420: flags |= FORCECLOSE;
! 421:
! 422: if ((error = vflush(mp, NULL, flags)))
! 423: return (error);
! 424:
! 425: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
! 426: vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, 0);
! 427: error = VOP_CLOSE(devvp, FREAD, NOCRED, p);
! 428: VOP_UNLOCK(devvp, 0, p);
! 429: if (error)
! 430: return (error);
! 431:
! 432: devvp->v_specmountpoint = NULL;
! 433: vrele(devvp);
! 434:
! 435: if (ump->um_flags & UDF_MNT_USES_VAT)
! 436: free(ump->um_vat, M_UDFMOUNT);
! 437:
! 438: if (ump->um_stbl != NULL)
! 439: free(ump->um_stbl, M_UDFMOUNT);
! 440:
! 441: if (ump->um_hashtbl != NULL)
! 442: free(ump->um_hashtbl, M_UDFMOUNT);
! 443:
! 444: FREE(ump, M_UDFMOUNT);
! 445:
! 446: mp->mnt_data = (qaddr_t)0;
! 447: mp->mnt_flag &= ~MNT_LOCAL;
! 448:
! 449: return (0);
! 450: }
! 451:
! 452: int
! 453: udf_root(struct mount *mp, struct vnode **vpp)
! 454: {
! 455: struct umount *ump;
! 456: struct vnode *vp;
! 457: ino_t id;
! 458: int error;
! 459:
! 460: ump = VFSTOUDFFS(mp);
! 461:
! 462: id = udf_getid(&ump->um_root_icb);
! 463:
! 464: error = udf_vget(mp, id, vpp);
! 465: if (error)
! 466: return (error);
! 467:
! 468: vp = *vpp;
! 469: vp->v_flag |= VROOT;
! 470:
! 471: return (0);
! 472: }
! 473:
! 474: int
! 475: udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
! 476: struct proc *p)
! 477: {
! 478: return (EOPNOTSUPP);
! 479: }
! 480:
! 481: int
! 482: udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
! 483: {
! 484: struct umount *ump;
! 485:
! 486: ump = VFSTOUDFFS(mp);
! 487:
! 488: sbp->f_bsize = ump->um_bsize;
! 489: sbp->f_iosize = ump->um_bsize;
! 490: sbp->f_blocks = ump->um_len;
! 491: sbp->f_bfree = 0;
! 492: sbp->f_bavail = 0;
! 493: sbp->f_files = 0;
! 494: sbp->f_ffree = 0;
! 495:
! 496: return (0);
! 497: }
! 498:
! 499: int
! 500: udf_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
! 501: {
! 502: return (0);
! 503: }
! 504:
! 505: int
! 506: udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
! 507: {
! 508: struct buf *bp;
! 509: struct vnode *devvp;
! 510: struct umount *ump;
! 511: struct proc *p;
! 512: struct vnode *vp;
! 513: struct unode *up;
! 514: struct file_entry *fe;
! 515: int error, sector, size;
! 516:
! 517: p = curproc;
! 518: bp = NULL;
! 519: *vpp = NULL;
! 520: ump = VFSTOUDFFS(mp);
! 521:
! 522: /* See if we already have this in the cache */
! 523: if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0)
! 524: return (error);
! 525: if (*vpp != NULL)
! 526: return (0);
! 527:
! 528: /*
! 529: * Allocate memory and check the tag id's before grabbing a new
! 530: * vnode, since it's hard to roll back if there is a problem.
! 531: */
! 532: up = pool_get(&unode_pool, PR_WAITOK);
! 533: bzero(up, sizeof(struct unode));
! 534:
! 535: /*
! 536: * Copy in the file entry. Per the spec, the size can only be 1 block.
! 537: */
! 538: sector = ino;
! 539: devvp = ump->um_devvp;
! 540: udf_vat_map(ump, §or);
! 541: if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
! 542: printf("Cannot read sector %d\n", sector);
! 543: pool_put(&unode_pool, up);
! 544: if (bp != NULL)
! 545: brelse(bp);
! 546: return (error);
! 547: }
! 548:
! 549: fe = (struct file_entry *)bp->b_data;
! 550: if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
! 551: printf("Invalid file entry!\n");
! 552: pool_put(&unode_pool, up);
! 553: brelse(bp);
! 554: return (ENOMEM);
! 555: }
! 556:
! 557: size = UDF_FENTRY_SIZE + letoh32(fe->l_ea) + letoh32(fe->l_ad);
! 558:
! 559: up->u_fentry = malloc(size, M_UDFFENTRY, M_NOWAIT);
! 560: if (up->u_fentry == NULL) {
! 561: pool_put(&unode_pool, up);
! 562: brelse(bp);
! 563: return (ENOMEM); /* Cannot allocate file entry block */
! 564: }
! 565:
! 566: bcopy(bp->b_data, up->u_fentry, size);
! 567:
! 568: brelse(bp);
! 569: bp = NULL;
! 570:
! 571: if ((error = udf_allocv(mp, &vp, p))) {
! 572: free(up->u_fentry, M_UDFFENTRY);
! 573: pool_put(&unode_pool, up);
! 574: return (error); /* Error from udf_allocv() */
! 575: }
! 576:
! 577: up->u_vnode = vp;
! 578: up->u_ino = ino;
! 579: up->u_devvp = ump->um_devvp;
! 580: up->u_dev = ump->um_dev;
! 581: up->u_ump = ump;
! 582: vp->v_data = up;
! 583: VREF(ump->um_devvp);
! 584:
! 585: lockinit(&up->u_lock, PINOD, "unode", 0, 0);
! 586:
! 587: /*
! 588: * udf_hashins() will lock the vnode for us.
! 589: */
! 590: udf_hashins(up);
! 591:
! 592: switch (up->u_fentry->icbtag.file_type) {
! 593: default:
! 594: vp->v_type = VBAD;
! 595: break;
! 596: case UDF_ICB_TYPE_DIR:
! 597: vp->v_type = VDIR;
! 598: break;
! 599: case UDF_ICB_TYPE_FILE:
! 600: vp->v_type = VREG;
! 601: break;
! 602: case UDF_ICB_TYPE_BLKDEV:
! 603: vp->v_type = VBLK;
! 604: break;
! 605: case UDF_ICB_TYPE_CHRDEV:
! 606: vp->v_type = VCHR;
! 607: break;
! 608: case UDF_ICB_TYPE_FIFO:
! 609: vp->v_type = VFIFO;
! 610: break;
! 611: case UDF_ICB_TYPE_SOCKET:
! 612: vp->v_type = VSOCK;
! 613: break;
! 614: case UDF_ICB_TYPE_SYMLINK:
! 615: vp->v_type = VLNK;
! 616: break;
! 617: case UDF_ICB_TYPE_VAT_150:
! 618: vp->v_type = VREG;
! 619: break;
! 620: }
! 621:
! 622: *vpp = vp;
! 623:
! 624: return (0);
! 625: }
! 626:
! 627: struct ifid {
! 628: u_short ifid_len;
! 629: u_short ifid_pad;
! 630: int ifid_ino;
! 631: long ifid_start;
! 632: };
! 633:
! 634: int
! 635: udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
! 636: {
! 637: struct ifid *ifhp;
! 638: struct vnode *nvp;
! 639: int error;
! 640:
! 641: ifhp = (struct ifid *)fhp;
! 642:
! 643: if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
! 644: *vpp = NULLVP;
! 645: return (error);
! 646: }
! 647:
! 648: *vpp = nvp;
! 649:
! 650: return (0);
! 651: }
! 652:
! 653: int
! 654: udf_vptofh(struct vnode *vp, struct fid *fhp)
! 655: {
! 656: struct unode *up;
! 657: struct ifid *ifhp;
! 658:
! 659: up = VTOU(vp);
! 660: ifhp = (struct ifid *)fhp;
! 661: ifhp->ifid_len = sizeof(struct ifid);
! 662: ifhp->ifid_ino = up->u_ino;
! 663:
! 664: return (0);
! 665: }
! 666:
! 667: int
! 668: udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
! 669: size_t newlen, struct proc *p)
! 670: {
! 671: return (EINVAL);
! 672: }
! 673:
! 674: int
! 675: udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
! 676: struct ucred **credanonp)
! 677: {
! 678: return (EACCES); /* For the time being */
! 679: }
! 680:
! 681: /* Handle a virtual partition map */
! 682: int
! 683: udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv)
! 684: {
! 685: ump->um_flags |= UDF_MNT_FIND_VAT; /* Should do more than this */
! 686: return (0);
! 687: }
! 688:
! 689: /* Handle a sparable partition map */
! 690: int
! 691: udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
! 692: {
! 693: struct buf *bp;
! 694: int i, error;
! 695:
! 696: ump->um_stbl = malloc(letoh32(pms->st_size), M_UDFMOUNT, M_NOWAIT);
! 697: if (ump->um_stbl == NULL)
! 698: return (ENOMEM);
! 699:
! 700: bzero(ump->um_stbl, letoh32(pms->st_size));
! 701:
! 702: /* Calculate the number of sectors per packet */
! 703: ump->um_psecs = letoh16(pms->packet_len) / ump->um_bsize;
! 704:
! 705: error = udf_readlblks(ump, letoh32(pms->st_loc[0]),
! 706: letoh32(pms->st_size), &bp);
! 707:
! 708: if (error) {
! 709: if (bp != NULL)
! 710: brelse(bp);
! 711: free(ump->um_stbl, M_UDFMOUNT);
! 712: return (error); /* Failed to read sparing table */
! 713: }
! 714:
! 715: bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size));
! 716: brelse(bp);
! 717:
! 718: if (udf_checktag(&ump->um_stbl->tag, 0)) {
! 719: free(ump->um_stbl, M_UDFMOUNT);
! 720: return (EINVAL); /* Invalid sparing table found */
! 721: }
! 722:
! 723: /*
! 724: * See how many valid entries there are here. The list is
! 725: * supposed to be sorted, 0xfffffff0 and higher are not valid.
! 726: */
! 727: for (i = 0; i < letoh16(ump->um_stbl->rt_l); i++) {
! 728: ump->um_stbl_len = i;
! 729: if (letoh32(ump->um_stbl->entries[i].org) >= 0xfffffff0)
! 730: break;
! 731: }
! 732:
! 733: return (0);
! 734: }
! 735:
! 736: /* Scan the partition maps */
! 737: int
! 738: udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd)
! 739: {
! 740: struct regid *pmap_id;
! 741: unsigned char regid_id[UDF_REGID_ID_SIZE + 1];
! 742: int i, ptype, psize, error;
! 743: uint8_t *pmap = (uint8_t *) &lvd->maps[0];
! 744:
! 745: for (i = 0; i < letoh32(lvd->n_pm); i++) {
! 746: ptype = pmap[0];
! 747: psize = pmap[1];
! 748:
! 749: if (ptype != 1 && ptype != 2)
! 750: return (EINVAL); /* Invalid partition map type */
! 751:
! 752: if (psize != UDF_PMAP_TYPE1_SIZE &&
! 753: psize != UDF_PMAP_TYPE2_SIZE)
! 754: return (EINVAL); /* Invalid partition map size */
! 755:
! 756: if (ptype == 1) {
! 757: pmap += UDF_PMAP_TYPE1_SIZE;
! 758: continue;
! 759: }
! 760:
! 761: /* Type 2 map. Find out the details */
! 762: pmap_id = (struct regid *) &pmap[4];
! 763: regid_id[UDF_REGID_ID_SIZE] = '\0';
! 764: bcopy(&pmap_id->id[0], ®id_id[0], UDF_REGID_ID_SIZE);
! 765:
! 766: if (!bcmp(®id_id[0], "*UDF Virtual Partition",
! 767: UDF_REGID_ID_SIZE))
! 768: error = udf_get_vpartmap(ump,
! 769: (struct part_map_virt *) pmap);
! 770: else if (!bcmp(®id_id[0], "*UDF Sparable Partition",
! 771: UDF_REGID_ID_SIZE))
! 772: error = udf_get_spartmap(ump,
! 773: (struct part_map_spare *) pmap);
! 774: else
! 775: return (EINVAL); /* Unsupported partition map */
! 776:
! 777: if (error)
! 778: return (error); /* Error getting partition */
! 779:
! 780: pmap += UDF_PMAP_TYPE2_SIZE;
! 781: }
! 782:
! 783: return (0);
! 784: }
CVSweb