[BACK]Return to udf_vfsops.c CVS log [TXT][DIR] Up to [local] / sys / isofs / udf

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, &sector);
        !           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, &sector);
        !           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, &sector);
        !           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], &regid_id[0], UDF_REGID_ID_SIZE);
        !           765:
        !           766:                if (!bcmp(&regid_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(&regid_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