root/isofs/cd9660/cd9660_vfsops.c

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

DEFINITIONS

This source file includes following definitions.
  1. cd9660_mountroot
  2. cd9660_mount
  3. iso_mountfs
  4. iso_disklabelspoof
  5. cd9660_start
  6. cd9660_unmount
  7. cd9660_root
  8. cd9660_quotactl
  9. cd9660_statfs
  10. cd9660_sync
  11. cd9660_fhtovp
  12. cd9660_vget
  13. cd9660_vget_internal
  14. cd9660_vptofh
  15. cd9660_check_export

    1 /*      $OpenBSD: cd9660_vfsops.c,v 1.46 2007/06/08 05:35:32 deraadt Exp $      */
    2 /*      $NetBSD: cd9660_vfsops.c,v 1.26 1997/06/13 15:38:58 pk Exp $    */
    3 
    4 /*-
    5  * Copyright (c) 1994
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley
    9  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
   10  * Support code is derived from software contributed to Berkeley
   11  * by Atsushi Murai (amurai@spec.co.jp).
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)cd9660_vfsops.c     8.9 (Berkeley) 12/5/94
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/namei.h>
   43 #include <sys/proc.h>
   44 #include <sys/kernel.h>
   45 #include <sys/vnode.h>
   46 #include <miscfs/specfs/specdev.h>
   47 #include <sys/mount.h>
   48 #include <sys/buf.h>
   49 #include <sys/file.h>
   50 #include <sys/disklabel.h>
   51 #include <sys/ioctl.h>
   52 #include <sys/cdio.h>
   53 #include <sys/conf.h>
   54 #include <sys/errno.h>
   55 #include <sys/malloc.h>
   56 #include <sys/stat.h>
   57 
   58 #include <isofs/cd9660/iso.h>
   59 #include <isofs/cd9660/cd9660_extern.h>
   60 #include <isofs/cd9660/iso_rrip.h>
   61 #include <isofs/cd9660/cd9660_node.h>
   62 
   63 const struct vfsops cd9660_vfsops = {
   64         cd9660_mount,
   65         cd9660_start,
   66         cd9660_unmount,
   67         cd9660_root,
   68         cd9660_quotactl,
   69         cd9660_statfs,
   70         cd9660_sync,
   71         cd9660_vget,
   72         cd9660_fhtovp,
   73         cd9660_vptofh,
   74         cd9660_init,
   75         cd9660_sysctl,
   76         cd9660_check_export
   77 };
   78 
   79 /*
   80  * Called by vfs_mountroot when iso is going to be mounted as root.
   81  */
   82 
   83 static  int iso_mountfs(struct vnode *devvp, struct mount *mp,
   84             struct proc *p, struct iso_args *argp);
   85 int     iso_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
   86             struct disklabel *lp);
   87 
   88 int
   89 cd9660_mountroot()
   90 {
   91         struct mount *mp;
   92         extern struct vnode *rootvp;
   93         struct proc *p = curproc;       /* XXX */
   94         int error;
   95         struct iso_args args;
   96         
   97         /*
   98          * Get vnodes for swapdev and rootdev.
   99          */
  100         if ((error = bdevvp(swapdev, &swapdev_vp)) ||
  101             (error = bdevvp(rootdev, &rootvp))) {
  102                 printf("cd9660_mountroot: can't setup bdevvp's");
  103                 return (error);
  104         }
  105 
  106         if ((error = vfs_rootmountalloc("cd9660", "root_device", &mp)) != 0)
  107                 return (error);
  108         args.flags = ISOFSMNT_ROOT;
  109         if ((error = iso_mountfs(rootvp, mp, p, &args)) != 0) {
  110                 mp->mnt_vfc->vfc_refcount--;
  111                 vfs_unbusy(mp);
  112                 free(mp, M_MOUNT);
  113                 return (error);
  114         }
  115 
  116         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  117         (void)cd9660_statfs(mp, &mp->mnt_stat, p);
  118         vfs_unbusy(mp);
  119         inittodr(0);
  120 
  121         return (0);
  122 }
  123 
  124 /*
  125  * VFS Operations.
  126  *
  127  * mount system call
  128  */
  129 int
  130 cd9660_mount(mp, path, data, ndp, p)
  131         register struct mount *mp;
  132         const char *path;
  133         void *data;
  134         struct nameidata *ndp;
  135         struct proc *p;
  136 {
  137         struct vnode *devvp;
  138         struct iso_args args;
  139         size_t size;
  140         int error;
  141         struct iso_mnt *imp = NULL;
  142         
  143         error = copyin(data, &args, sizeof (struct iso_args));
  144         if (error)
  145                 return (error);
  146         
  147         if ((mp->mnt_flag & MNT_RDONLY) == 0)
  148                 return (EROFS);
  149         
  150         /*
  151          * If updating, check whether changing from read-only to
  152          * read/write; if there is no device name, that's all we do.
  153          */
  154         if (mp->mnt_flag & MNT_UPDATE) {
  155                 imp = VFSTOISOFS(mp);
  156                 if (args.fspec == 0)
  157                         return (vfs_export(mp, &imp->im_export, 
  158                             &args.export_info));
  159         }
  160         /*
  161          * Not an update, or updating the name: look up the name
  162          * and verify that it refers to a sensible block device.
  163          */
  164         NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
  165         if ((error = namei(ndp)) != 0)
  166                 return (error);
  167         devvp = ndp->ni_vp;
  168 
  169         if (devvp->v_type != VBLK) {
  170                 vrele(devvp);
  171                 return (ENOTBLK);
  172         }
  173         if (major(devvp->v_rdev) >= nblkdev) {
  174                 vrele(devvp);
  175                 return (ENXIO);
  176         }
  177         /*
  178          * If mount by non-root, then verify that user has necessary
  179          * permissions on the device.
  180          */
  181         if (p->p_ucred->cr_uid != 0) {
  182                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  183                 error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p);
  184                 if (error) {
  185                         vput(devvp);
  186                         return (error);
  187                 }
  188                 VOP_UNLOCK(devvp, 0, p);
  189         }
  190         if ((mp->mnt_flag & MNT_UPDATE) == 0)
  191                 error = iso_mountfs(devvp, mp, p, &args);
  192         else {
  193                 if (devvp != imp->im_devvp)
  194                         error = EINVAL; /* needs translation */
  195                 else
  196                         vrele(devvp);
  197         }
  198         if (error) {
  199                 vrele(devvp);
  200                 return (error);
  201         }
  202         imp = VFSTOISOFS(mp);
  203         (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
  204         bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
  205         (void)copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
  206             &size);
  207         bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  208         bcopy(&args, &mp->mnt_stat.mount_info.iso_args, sizeof(args));
  209         (void)cd9660_statfs(mp, &mp->mnt_stat, p);
  210         return (0);
  211 }
  212 
  213 /*
  214  * Common code for mount and mountroot
  215  */
  216 static int
  217 iso_mountfs(devvp, mp, p, argp)
  218         register struct vnode *devvp;
  219         struct mount *mp;
  220         struct proc *p;
  221         struct iso_args *argp;
  222 {
  223         register struct iso_mnt *isomp = (struct iso_mnt *)0;
  224         struct buf *bp = NULL;
  225         struct buf *pribp = NULL, *supbp = NULL;
  226         dev_t dev = devvp->v_rdev;
  227         int error = EINVAL;
  228         int needclose = 0;
  229         int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  230         extern struct vnode *rootvp;
  231         int iso_bsize;
  232         int iso_blknum;
  233         int joliet_level;
  234         struct iso_volume_descriptor *vdp;
  235         struct iso_primary_descriptor *pri = NULL;
  236         struct iso_supplementary_descriptor *sup = NULL;
  237         struct iso_directory_record *rootp;
  238         int logical_block_size;
  239         int sess;
  240         
  241         if (!ronly)
  242                 return (EROFS);
  243         
  244         /*
  245          * Disallow multiple mounts of the same device.
  246          * Disallow mounting of a device that is currently in use
  247          * (except for root, which might share swap device for miniroot).
  248          * Flush out any old buffers remaining from a previous use.
  249          */
  250         if ((error = vfs_mountedon(devvp)) != 0)
  251                 return (error);
  252         if (vcount(devvp) > 1 && devvp != rootvp)
  253                 return (EBUSY);
  254         if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
  255                 return (error);
  256 
  257         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
  258         if (error)
  259                 return (error);
  260         needclose = 1;
  261         
  262         /*
  263          * This is the "logical sector size".  The standard says this
  264          * should be 2048 or the physical sector size on the device,
  265          * whichever is greater.  For now, we'll just use a constant.
  266          */
  267         iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
  268 
  269         if (argp->flags & ISOFSMNT_SESS) {
  270                 sess = argp->sess;
  271                 if (sess < 0)
  272                         sess = 0;
  273         } else {
  274                 sess = 0;
  275                 error = VOP_IOCTL(devvp, CDIOREADMSADDR, (caddr_t)&sess, 0,
  276                     FSCRED, p);
  277                 if (error)
  278                         sess = 0;
  279         }
  280 
  281         joliet_level = 0;
  282         for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
  283                 if ((error = bread(devvp,
  284                     (iso_blknum + sess) * btodb(iso_bsize),
  285                     iso_bsize, NOCRED, &bp)) != 0)
  286                         goto out;
  287                 
  288                 vdp = (struct iso_volume_descriptor *)bp->b_data;
  289                 if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
  290                         error = EINVAL;
  291                         goto out;
  292                 }
  293                 
  294                 switch (isonum_711 (vdp->type)){
  295                 case ISO_VD_PRIMARY:
  296                         if (pribp == NULL) {
  297                                 pribp = bp;
  298                                 bp = NULL;
  299                                 pri = (struct iso_primary_descriptor *)vdp;
  300                         }
  301                         break;
  302                 case ISO_VD_SUPPLEMENTARY:
  303                         if (supbp == NULL) {
  304                                 supbp = bp;
  305                                 bp = NULL;
  306                                 sup = (struct iso_supplementary_descriptor *)vdp;
  307   
  308                                 if (!(argp->flags & ISOFSMNT_NOJOLIET)) {
  309                                         if (bcmp(sup->escape, "%/@", 3) == 0)
  310                                                 joliet_level = 1;
  311                                         if (bcmp(sup->escape, "%/C", 3) == 0)
  312                                                 joliet_level = 2;
  313                                         if (bcmp(sup->escape, "%/E", 3) == 0)
  314                                                 joliet_level = 3;
  315   
  316                                         if (isonum_711 (sup->flags) & 1)
  317                                                 joliet_level = 0;
  318                                 }
  319                         }
  320                         break;
  321   
  322                 case ISO_VD_END:
  323                         goto vd_end;
  324   
  325                 default:
  326                         break;
  327                 }
  328                 if (bp) {
  329                         brelse(bp);
  330                         bp = NULL;
  331                 }
  332         }
  333     vd_end:
  334         if (bp) {
  335                 brelse(bp);
  336                 bp = NULL;
  337         }
  338   
  339         if (pri == NULL) {
  340                 error = EINVAL;
  341                 goto out;
  342         }
  343 
  344         logical_block_size = isonum_723 (pri->logical_block_size);
  345         
  346         if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
  347             || (logical_block_size & (logical_block_size - 1)) != 0) {
  348                 error = EINVAL;
  349                 goto out;
  350         }
  351         
  352         rootp = (struct iso_directory_record *)pri->root_directory_record;
  353         
  354         isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
  355         bzero((caddr_t)isomp, sizeof *isomp);
  356         isomp->logical_block_size = logical_block_size;
  357         isomp->volume_space_size = isonum_733 (pri->volume_space_size);
  358         bcopy (rootp, isomp->root, sizeof isomp->root);
  359         isomp->root_extent = isonum_733 (rootp->extent);
  360         isomp->root_size = isonum_733 (rootp->size);
  361         isomp->joliet_level = 0;
  362         /*                                                                  
  363          * Since an ISO9660 multi-session CD can also access previous sessions,
  364          * we have to include them into the space considerations.
  365          */
  366         isomp->volume_space_size += sess;
  367         isomp->im_bmask = logical_block_size - 1;
  368         isomp->im_bshift = ffs(logical_block_size) - 1;
  369 
  370         pribp->b_flags |= B_AGE;
  371         brelse(pribp);
  372         pribp = NULL;
  373         
  374         mp->mnt_data = (qaddr_t)isomp;
  375         mp->mnt_stat.f_fsid.val[0] = (long)dev;
  376         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
  377         mp->mnt_maxsymlinklen = 0;
  378         mp->mnt_flag |= MNT_LOCAL;
  379         isomp->im_mountp = mp;
  380         isomp->im_dev = dev;
  381         isomp->im_devvp = devvp;
  382 
  383         /* Check the Rock Ridge Extension support */
  384         if (!(argp->flags & ISOFSMNT_NORRIP)) {
  385                 if ((error = bread(isomp->im_devvp, (isomp->root_extent +
  386                     isonum_711(rootp->ext_attr_length)) <<
  387                     (isomp->im_bshift - DEV_BSHIFT),
  388                     isomp->logical_block_size, NOCRED, &bp)) != 0)
  389                         goto out;
  390                 
  391                 rootp = (struct iso_directory_record *)bp->b_data;
  392                 
  393                 if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
  394                     argp->flags  |= ISOFSMNT_NORRIP;
  395                 } else {
  396                     argp->flags  &= ~ISOFSMNT_GENS;
  397                 }
  398                 
  399                 /*
  400                  * The contents are valid,
  401                  * but they will get reread as part of another vnode, so...
  402                  */
  403                 bp->b_flags |= B_AGE;
  404                 brelse(bp);
  405                 bp = NULL;
  406         }
  407         isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
  408             ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
  409         switch (isomp->im_flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS)) {
  410         default:
  411             isomp->iso_ftype = ISO_FTYPE_DEFAULT;
  412             break;
  413         case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
  414             isomp->iso_ftype = ISO_FTYPE_9660;
  415             break;
  416         case 0:
  417             isomp->iso_ftype = ISO_FTYPE_RRIP;
  418             break;
  419         }
  420 
  421         /* Decide whether to use the Joliet descriptor */
  422   
  423         if (isomp->iso_ftype != ISO_FTYPE_RRIP && joliet_level) {
  424                 rootp = (struct iso_directory_record *)
  425                         sup->root_directory_record;
  426                 bcopy(rootp, isomp->root, sizeof isomp->root);
  427                 isomp->root_extent = isonum_733(rootp->extent);
  428                 isomp->root_size = isonum_733(rootp->size);
  429                 isomp->joliet_level = joliet_level;
  430                 supbp->b_flags |= B_AGE;
  431         }
  432   
  433         if (supbp) {
  434                 brelse(supbp);
  435                 supbp = NULL;
  436         }
  437   
  438         devvp->v_specmountpoint = mp;
  439 
  440         return (0);
  441 out:
  442         if (bp)
  443                 brelse(bp);
  444         if (supbp)
  445                 brelse(supbp);
  446         if (needclose)
  447                 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED,
  448                     p);
  449         if (isomp) {
  450                 free((caddr_t)isomp, M_ISOFSMNT);
  451                 mp->mnt_data = (qaddr_t)0;
  452         }
  453         return (error);
  454 }
  455 
  456 /*
  457  * Test to see if the device is an ISOFS filesystem.
  458  */
  459 int
  460 iso_disklabelspoof(dev, strat, lp)
  461         dev_t dev;
  462         void (*strat)(struct buf *);
  463         register struct disklabel *lp;
  464 {
  465         struct buf *bp = NULL;
  466         struct iso_volume_descriptor *vdp;
  467         struct iso_primary_descriptor *pri;
  468         int logical_block_size;
  469         int error = EINVAL;
  470         int iso_blknum;
  471         int i;
  472 
  473         bp = geteblk(ISO_DEFAULT_BLOCK_SIZE);
  474         bp->b_dev = dev;
  475 
  476         for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
  477                 bp->b_blkno = iso_blknum * btodb(ISO_DEFAULT_BLOCK_SIZE);
  478                 bp->b_bcount = ISO_DEFAULT_BLOCK_SIZE;
  479                 bp->b_flags = B_BUSY | B_READ;
  480                 bp->b_cylinder = bp->b_blkno / lp->d_secpercyl;
  481 
  482                 /*printf("d_secsize %d iso_blknum %d b_blkno %d bcount %d\n",
  483                     lp->d_secsize, iso_blknum, bp->b_blkno, bp->b_bcount);*/
  484 
  485                 (*strat)(bp);
  486 
  487                 if (biowait(bp))
  488                         goto out;
  489 
  490                 vdp = (struct iso_volume_descriptor *)bp->b_data;
  491                 /*printf("%2x%2x%2x type %2x\n", vdp->id[0], vdp->id[1],
  492                     vdp->id[2], isonum_711(vdp->type));*/
  493                 if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0 ||
  494                     isonum_711 (vdp->type) == ISO_VD_END)
  495                         goto out;
  496                 
  497                 if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
  498                         break;
  499         }
  500         
  501         if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
  502                 goto out;
  503         
  504         pri = (struct iso_primary_descriptor *)vdp;
  505         logical_block_size = isonum_723 (pri->logical_block_size);
  506         if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE ||
  507             (logical_block_size & (logical_block_size - 1)) != 0)
  508                 goto out;
  509 
  510         /*
  511          * build a disklabel for the CD
  512          */
  513         strncpy(lp->d_typename, pri->volume_id, sizeof lp->d_typename);
  514         strncpy(lp->d_packname, pri->volume_id+16, sizeof lp->d_packname);
  515         for (i = 0; i < MAXPARTITIONS; i++) {
  516                 DL_SETPSIZE(&lp->d_partitions[i], 0);
  517                 DL_SETPOFFSET(&lp->d_partitions[i], 0);
  518         }
  519         DL_SETPOFFSET(&lp->d_partitions[0], 0);
  520         DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp));
  521         lp->d_partitions[0].p_fstype = FS_ISO9660;
  522         DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
  523         DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
  524         lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660;
  525         lp->d_npartitions = RAW_PART + 1;
  526         lp->d_bbsize = 8192;            /* fake */
  527         lp->d_sbsize = 64*1024;         /* fake */
  528         lp->d_version = 1;
  529 
  530         lp->d_magic = DISKMAGIC;
  531         lp->d_magic2 = DISKMAGIC;
  532         lp->d_checksum = dkcksum(lp);
  533         error = 0;
  534 out:
  535         bp->b_flags |= B_INVAL;
  536         brelse(bp);
  537         return (error);
  538 }
  539 
  540 /*
  541  * Make a filesystem operational.
  542  * Nothing to do at the moment.
  543  */
  544 /* ARGSUSED */
  545 int
  546 cd9660_start(mp, flags, p)
  547         struct mount *mp;
  548         int flags;
  549         struct proc *p;
  550 {
  551         return (0);
  552 }
  553 
  554 /*
  555  * unmount system call
  556  */
  557 int
  558 cd9660_unmount(mp, mntflags, p)
  559         struct mount *mp;
  560         int mntflags;
  561         struct proc *p;
  562 {
  563         register struct iso_mnt *isomp;
  564         int error, flags = 0;
  565         
  566         if (mntflags & MNT_FORCE)
  567                 flags |= FORCECLOSE;
  568 #if 0
  569         mntflushbuf(mp, 0);
  570         if (mntinvalbuf(mp))
  571                 return (EBUSY);
  572 #endif
  573         if ((error = vflush(mp, NULLVP, flags)) != 0)
  574                 return (error);
  575 
  576         isomp = VFSTOISOFS(mp);
  577 
  578 #ifdef  ISODEVMAP
  579         if (isomp->iso_ftype == ISO_FTYPE_RRIP)
  580                 iso_dunmap(isomp->im_dev);
  581 #endif
  582         
  583         isomp->im_devvp->v_specmountpoint = NULL;
  584         error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
  585         vrele(isomp->im_devvp);
  586         free((caddr_t)isomp, M_ISOFSMNT);
  587         mp->mnt_data = (qaddr_t)0;
  588         mp->mnt_flag &= ~MNT_LOCAL;
  589         return (error);
  590 }
  591 
  592 /*
  593  * Return root of a filesystem
  594  */
  595 int
  596 cd9660_root(mp, vpp)
  597         struct mount *mp;
  598         struct vnode **vpp;
  599 {
  600         struct iso_mnt *imp = VFSTOISOFS(mp);
  601         struct iso_directory_record *dp =
  602             (struct iso_directory_record *)imp->root;
  603         ino_t ino = isodirino(dp, imp);
  604         
  605         /*
  606          * With RRIP we must use the `.' entry of the root directory.
  607          * Simply tell vget, that it's a relocated directory.
  608          */
  609         return (cd9660_vget_internal(mp, ino, vpp,
  610             imp->iso_ftype == ISO_FTYPE_RRIP, dp));
  611 }
  612 
  613 /*
  614  * Do operations associated with quotas, not supported
  615  */
  616 /* ARGSUSED */
  617 int
  618 cd9660_quotactl(mp, cmd, uid, arg, p)
  619         struct mount *mp;
  620         int cmd;
  621         uid_t uid;
  622         caddr_t arg;
  623         struct proc *p;
  624 {
  625 
  626         return (EOPNOTSUPP);
  627 }
  628 
  629 /*
  630  * Get file system statistics.
  631  */
  632 int
  633 cd9660_statfs(mp, sbp, p)
  634         struct mount *mp;
  635         register struct statfs *sbp;
  636         struct proc *p;
  637 {
  638         register struct iso_mnt *isomp;
  639         
  640         isomp = VFSTOISOFS(mp);
  641 
  642         sbp->f_bsize = isomp->logical_block_size;
  643         sbp->f_iosize = sbp->f_bsize;   /* XXX */
  644         sbp->f_blocks = isomp->volume_space_size;
  645         sbp->f_bfree = 0; /* total free blocks */
  646         sbp->f_bavail = 0; /* blocks free for non superuser */
  647         sbp->f_files =  0; /* total files */
  648         sbp->f_ffree = 0; /* free file nodes */
  649         if (sbp != &mp->mnt_stat) {
  650                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  651                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname,
  652                     MNAMELEN);
  653                 bcopy(&mp->mnt_stat.mount_info.iso_args,
  654                     &sbp->mount_info.iso_args, sizeof(struct iso_args));
  655         }
  656         /* Use the first spare for flags: */
  657         sbp->f_spare[0] = isomp->im_flags;
  658         return (0);
  659 }
  660 
  661 /* ARGSUSED */
  662 int
  663 cd9660_sync(mp, waitfor, cred, p)
  664         struct mount *mp;
  665         int waitfor;
  666         struct ucred *cred;
  667         struct proc *p;
  668 {
  669         return (0);
  670 }
  671 
  672 /*
  673  * File handle to vnode
  674  *
  675  * Have to be really careful about stale file handles:
  676  * - check that the inode number is in range
  677  * - call iget() to get the locked inode
  678  * - check for an unallocated inode (i_mode == 0)
  679  * - check that the generation number matches
  680  */
  681 
  682 struct ifid {
  683         ushort  ifid_len;
  684         ushort  ifid_pad;
  685         int     ifid_ino;
  686         long    ifid_start;
  687 };
  688 
  689 /* ARGSUSED */
  690 int
  691 cd9660_fhtovp(mp, fhp, vpp)
  692         register struct mount *mp;
  693         struct fid *fhp;
  694         struct vnode **vpp;
  695 {
  696         struct ifid *ifhp = (struct ifid *)fhp;
  697         register struct iso_node *ip;
  698         struct vnode *nvp;
  699         int error;
  700         
  701 #ifdef  ISOFS_DBG
  702         printf("fhtovp: ino %d, start %ld\n", ifhp->ifid_ino,
  703             ifhp->ifid_start);
  704 #endif
  705         
  706         if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
  707                 *vpp = NULLVP;
  708                 return (error);
  709         }
  710         ip = VTOI(nvp);
  711         if (ip->inode.iso_mode == 0) {
  712                 vput(nvp);
  713                 *vpp = NULLVP;
  714                 return (ESTALE);
  715         }
  716         *vpp = nvp;
  717         return (0);
  718 }
  719 
  720 int
  721 cd9660_vget(mp, ino, vpp)
  722         struct mount *mp;
  723         ino_t ino;
  724         struct vnode **vpp;
  725 {
  726 
  727         /*
  728          * XXXX
  729          * It would be nice if we didn't always set the `relocated' flag
  730          * and force the extra read, but I don't want to think about fixing
  731          * that right now.
  732          */
  733         return (cd9660_vget_internal(mp, ino, vpp,
  734 #if 0
  735             VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
  736 #else
  737             0,
  738 #endif
  739             NULL));
  740 }
  741 
  742 int
  743 cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
  744         struct mount *mp;
  745         ino_t ino;
  746         struct vnode **vpp;
  747         int relocated;
  748         struct iso_directory_record *isodir;
  749 {
  750         register struct iso_mnt *imp;
  751         struct iso_node *ip;
  752         struct buf *bp;
  753         struct vnode *vp, *nvp;
  754         dev_t dev;
  755         int error;
  756 
  757 retry:
  758         imp = VFSTOISOFS(mp);
  759         dev = imp->im_dev;
  760         if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
  761                 return (0);
  762 
  763         /* Allocate a new vnode/iso_node. */
  764         if ((error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) != 0) {
  765                 *vpp = NULLVP;
  766                 return (error);
  767         }
  768         MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
  769             M_WAITOK);
  770         bzero((caddr_t)ip, sizeof(struct iso_node));
  771         lockinit(&ip->i_lock, PINOD, "isoinode", 0, 0);
  772         vp->v_data = ip;
  773         ip->i_vnode = vp;
  774         ip->i_dev = dev;
  775         ip->i_number = ino;
  776 
  777         /*
  778          * Put it onto its hash chain and lock it so that other requests for
  779          * this inode will block if they arrive while we are sleeping waiting
  780          * for old data structures to be purged or for the contents of the
  781          * disk portion of this inode to be read.
  782          */
  783         error = cd9660_ihashins(ip);
  784 
  785         if (error) {
  786                 vrele(vp);
  787 
  788                 if (error == EEXIST)
  789                         goto retry;
  790 
  791                 return (error);
  792         }
  793 
  794         if (isodir == 0) {
  795                 int lbn, off;
  796 
  797                 lbn = lblkno(imp, ino);
  798                 if (lbn >= imp->volume_space_size) {
  799                         vput(vp);
  800                         printf("fhtovp: lbn exceed volume space %d\n", lbn);
  801                         return (ESTALE);
  802                 }
  803         
  804                 off = blkoff(imp, ino);
  805                 if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size)
  806                     {
  807                         vput(vp);
  808                         printf("fhtovp: crosses block boundary %d\n",
  809                             off + ISO_DIRECTORY_RECORD_SIZE);
  810                         return (ESTALE);
  811                 }
  812         
  813                 error = bread(imp->im_devvp,
  814                               lbn << (imp->im_bshift - DEV_BSHIFT),
  815                               imp->logical_block_size, NOCRED, &bp);
  816                 if (error) {
  817                         vput(vp);
  818                         brelse(bp);
  819                         printf("fhtovp: bread error %d\n",error);
  820                         return (error);
  821                 }
  822                 isodir = (struct iso_directory_record *)(bp->b_data + off);
  823 
  824                 if (off + isonum_711(isodir->length) >
  825                     imp->logical_block_size) {
  826                         vput(vp);
  827                         if (bp != 0)
  828                                 brelse(bp);
  829                         printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
  830                             off +isonum_711(isodir->length), off,
  831                             isonum_711(isodir->length));
  832                         return (ESTALE);
  833                 }
  834         
  835 #if 0
  836                 if (isonum_733(isodir->extent) +
  837                     isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
  838                         if (bp != 0)
  839                                 brelse(bp);
  840                         printf("fhtovp: file start miss %d vs %d\n",
  841                             isonum_733(isodir->extent) +
  842                             isonum_711(isodir->ext_attr_length),
  843                             ifhp->ifid_start);
  844                         return (ESTALE);
  845                 }
  846 #endif
  847         } else
  848                 bp = 0;
  849 
  850         ip->i_mnt = imp;
  851         ip->i_devvp = imp->im_devvp;
  852         VREF(ip->i_devvp);
  853 
  854         if (relocated) {
  855                 /*
  856                  * On relocated directories we must
  857                  * read the `.' entry out of a dir.
  858                  */
  859                 ip->iso_start = ino >> imp->im_bshift;
  860                 if (bp != 0)
  861                         brelse(bp);
  862                 if ((error = cd9660_bufatoff(ip, (off_t)0, NULL, &bp)) != 0) {
  863                         vput(vp);
  864                         return (error);
  865                 }
  866                 isodir = (struct iso_directory_record *)bp->b_data;
  867         }
  868 
  869         ip->iso_extent = isonum_733(isodir->extent);
  870         ip->i_size = (u_int32_t) isonum_733(isodir->size);
  871         ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
  872         
  873         /*
  874          * Setup time stamp, attribute
  875          */
  876         vp->v_type = VNON;
  877         switch (imp->iso_ftype) {
  878         default:        /* ISO_FTYPE_9660 */
  879             {
  880                 struct buf *bp2;
  881                 int off;
  882                 if ((imp->im_flags & ISOFSMNT_EXTATT) && 
  883                     (off = isonum_711(isodir->ext_attr_length)))
  884                         cd9660_bufatoff(ip, (off_t)-(off << imp->im_bshift),
  885                             NULL, &bp2);
  886                 else
  887                         bp2 = NULL;
  888                 cd9660_defattr(isodir, ip, bp2);
  889                 cd9660_deftstamp(isodir, ip, bp2);
  890                 if (bp2)
  891                         brelse(bp2);
  892                 break;
  893             }
  894         case ISO_FTYPE_RRIP:
  895                 cd9660_rrip_analyze(isodir, ip, imp);
  896                 break;
  897         }
  898 
  899         if (bp != 0)
  900                 brelse(bp);
  901 
  902         /*
  903          * Initialize the associated vnode
  904          */
  905         switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
  906         case VFIFO:
  907 #ifdef  FIFO
  908                 vp->v_op = cd9660_fifoop_p;
  909                 break;
  910 #else
  911                 vput(vp);
  912                 return (EOPNOTSUPP);
  913 #endif  /* FIFO */
  914         case VCHR:
  915         case VBLK:
  916                 /*
  917                  * if device, look at device number table for translation
  918                  */
  919 #ifdef  ISODEVMAP
  920                 if (dp = iso_dmap(dev, ino, 0))
  921                         ip->inode.iso_rdev = dp->d_dev;
  922 #endif
  923                 vp->v_op = cd9660_specop_p;
  924                 if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) {
  925                         /*
  926                          * Discard unneeded vnode, but save its iso_node.
  927                          * Note that the lock is carried over in the iso_node
  928                          */
  929                         nvp->v_data = vp->v_data;
  930                         vp->v_data = NULL;
  931                         vp->v_op = spec_vnodeop_p;
  932                         vrele(vp);
  933                         vgone(vp);
  934                         /*
  935                          * Reinitialize aliased inode.
  936                          */
  937                         vp = nvp;
  938                         ip->i_vnode = vp;
  939                 }
  940                 break;
  941         case VLNK:
  942         case VNON:
  943         case VSOCK:
  944         case VDIR:
  945         case VBAD:
  946                 break;
  947         case VREG:
  948                 uvm_vnp_setsize(vp, ip->i_size);
  949                 break;
  950         }
  951         
  952         if (ip->iso_extent == imp->root_extent)
  953                 vp->v_flag |= VROOT;
  954 
  955         /*
  956          * XXX need generation number?
  957          */
  958         
  959         *vpp = vp;
  960         return (0);
  961 }
  962 
  963 /*
  964  * Vnode pointer to File handle
  965  */
  966 /* ARGSUSED */
  967 int
  968 cd9660_vptofh(vp, fhp)
  969         struct vnode *vp;
  970         struct fid *fhp;
  971 {
  972         register struct iso_node *ip = VTOI(vp);
  973         register struct ifid *ifhp;
  974 
  975         ifhp = (struct ifid *)fhp;
  976         ifhp->ifid_len = sizeof(struct ifid);
  977         
  978         ifhp->ifid_ino = ip->i_number;
  979         ifhp->ifid_start = ip->iso_start;
  980         
  981 #ifdef  ISOFS_DBG
  982         printf("vptofh: ino %d, start %ld\n",
  983             ifhp->ifid_ino,ifhp->ifid_start);
  984 #endif
  985         return (0);
  986 }
  987 
  988 /*
  989  * Verify a remote client has export rights and return these rights via
  990  * exflagsp and credanonp.
  991  */
  992 int
  993 cd9660_check_export(mp, nam, exflagsp, credanonp)
  994         register struct mount *mp;
  995         struct mbuf *nam;
  996         int *exflagsp;
  997         struct ucred **credanonp;
  998 {
  999         register struct netcred *np;
 1000         register struct iso_mnt *imp = VFSTOISOFS(mp);
 1001 
 1002         /*
 1003          * Get the export permission structure for this <mp, client> tuple.
 1004          */
 1005         np = vfs_export_lookup(mp, &imp->im_export, nam);
 1006         if (np == NULL)
 1007                 return (EACCES);
 1008 
 1009         *exflagsp = np->netc_exflags;
 1010         *credanonp = &np->netc_anon;
 1011         return (0);
 1012 }

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