LCOV - code coverage report
Current view: top level - isofs/cd9660 - cd9660_vfsops.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 419 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13