root/isofs/udf/udf_vfsops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. udf_init
  2. udf_start
  3. udf_mount
  4. udf_checktag
  5. udf_mountfs
  6. udf_unmount
  7. udf_root
  8. udf_quotactl
  9. udf_statfs
  10. udf_sync
  11. udf_vget
  12. udf_fhtovp
  13. udf_vptofh
  14. udf_sysctl
  15. udf_checkexp
  16. udf_get_vpartmap
  17. udf_get_spartmap
  18. udf_find_partmaps

    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 }

/* [<][>][^][v][top][bottom][index][help] */