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

          Line data    Source code
       1             : /*      $OpenBSD: cd9660_vnops.c,v 1.76 2016/06/19 11:54:33 natano Exp $        */
       2             : /*      $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos 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_vnops.c      8.15 (Berkeley) 12/5/94
      38             :  */
      39             : 
      40             : #include <sys/param.h>
      41             : #include <sys/systm.h>
      42             : #include <sys/namei.h>
      43             : #include <sys/resourcevar.h>
      44             : #include <sys/kernel.h>
      45             : #include <sys/file.h>
      46             : #include <sys/stat.h>
      47             : #include <sys/buf.h>
      48             : #include <sys/conf.h>
      49             : #include <sys/mount.h>
      50             : #include <sys/vnode.h>
      51             : #include <sys/lock.h>
      52             : #include <sys/malloc.h>
      53             : #include <sys/pool.h>
      54             : #include <sys/dirent.h>
      55             : #include <sys/ioctl.h>
      56             : #include <sys/ioccom.h>
      57             : #include <sys/poll.h>
      58             : #include <sys/specdev.h>
      59             : #include <sys/unistd.h>
      60             : 
      61             : #include <miscfs/fifofs/fifo.h>
      62             : 
      63             : #include <isofs/cd9660/iso.h>
      64             : #include <isofs/cd9660/cd9660_extern.h>
      65             : #include <isofs/cd9660/cd9660_node.h>
      66             : #include <isofs/cd9660/iso_rrip.h>
      67             : 
      68             : int cd9660_kqfilter(void *v);
      69             : 
      70             : 
      71             : /*
      72             :  * Structure for reading directories
      73             :  */
      74             : struct isoreaddir {
      75             :         struct dirent saveent;
      76             :         struct dirent assocent;
      77             :         struct dirent current;
      78             :         off_t saveoff;
      79             :         off_t assocoff;
      80             :         off_t curroff;
      81             :         struct uio *uio;
      82             :         off_t uio_off;
      83             :         int eofflag;
      84             : };
      85             : 
      86             : int     iso_uiodir(struct isoreaddir *, struct dirent *, off_t);
      87             : int     iso_shipdir(struct isoreaddir *);
      88             : 
      89             : /*
      90             :  * Setattr call. Only allowed for block and character special devices.
      91             :  */
      92             : int
      93           0 : cd9660_setattr(void *v)
      94             : {
      95           0 :         struct vop_setattr_args *ap = v;
      96           0 :         struct vnode *vp = ap->a_vp;
      97           0 :         struct vattr *vap = ap->a_vap;
      98             : 
      99           0 :         if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
     100           0 :             vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_nsec != VNOVAL ||
     101           0 :             vap->va_mtime.tv_nsec != VNOVAL || vap->va_mode != (mode_t)VNOVAL ||
     102           0 :             (vap->va_vaflags & VA_UTIMES_CHANGE))
     103           0 :                 return (EROFS);
     104           0 :         if (vap->va_size != VNOVAL) {
     105           0 :                 switch (vp->v_type) {
     106             :                 case VDIR:
     107           0 :                         return (EISDIR);
     108             :                 case VLNK:
     109             :                 case VREG:
     110           0 :                         return (EROFS);
     111             :                 case VCHR:
     112             :                 case VBLK:
     113             :                 case VSOCK:
     114             :                 case VFIFO:
     115           0 :                         return (0);
     116             :                 default:
     117           0 :                         return (EINVAL);
     118             :                 }
     119             :         }
     120             : 
     121           0 :         return (EINVAL);
     122           0 : }
     123             : 
     124             : /*
     125             :  * Open called.
     126             :  *
     127             :  * Nothing to do.
     128             :  */
     129             : /* ARGSUSED */
     130             : int
     131           0 : cd9660_open(void *v)
     132             : {
     133           0 :         return (0);
     134             : }
     135             : 
     136             : /*
     137             :  * Close called
     138             :  *
     139             :  * Update the times on the inode on writeable file systems.
     140             :  */
     141             : /* ARGSUSED */
     142             : int
     143           0 : cd9660_close(void *v)
     144             : {
     145           0 :         return (0);
     146             : }
     147             : 
     148             : /*
     149             :  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
     150             :  * The mode is shifted to select the owner/group/other fields. The
     151             :  * super user is granted all permissions.
     152             :  */
     153             : int
     154           0 : cd9660_access(void *v)
     155             : {
     156           0 :         struct vop_access_args *ap = v;
     157           0 :         struct iso_node *ip = VTOI(ap->a_vp);
     158             : 
     159           0 :         return (vaccess(ap->a_vp->v_type, ip->inode.iso_mode & ALLPERMS,
     160           0 :             ip->inode.iso_uid, ip->inode.iso_gid, ap->a_mode, ap->a_cred));
     161             : }
     162             : 
     163             : int
     164           0 : cd9660_getattr(void *v)
     165             : {
     166           0 :         struct vop_getattr_args *ap = v;
     167           0 :         struct vnode *vp = ap->a_vp;
     168           0 :         register struct vattr *vap = ap->a_vap;
     169           0 :         register struct iso_node *ip = VTOI(vp);
     170             : 
     171           0 :         vap->va_fsid = ip->i_dev;
     172           0 :         vap->va_fileid       = ip->i_number;
     173             : 
     174           0 :         vap->va_mode = ip->inode.iso_mode & ALLPERMS;
     175           0 :         vap->va_nlink        = ip->inode.iso_links;
     176           0 :         vap->va_uid  = ip->inode.iso_uid;
     177           0 :         vap->va_gid  = ip->inode.iso_gid;
     178           0 :         vap->va_atime        = ip->inode.iso_atime;
     179           0 :         vap->va_mtime        = ip->inode.iso_mtime;
     180           0 :         vap->va_ctime        = ip->inode.iso_ctime;
     181           0 :         vap->va_rdev = ip->inode.iso_rdev;
     182             : 
     183           0 :         vap->va_size = (u_quad_t) ip->i_size;
     184           0 :         if (ip->i_size == 0 && vp->v_type  == VLNK) {
     185           0 :                 struct vop_readlink_args rdlnk;
     186           0 :                 struct iovec aiov;
     187           0 :                 struct uio auio;
     188             :                 char *cp;
     189             : 
     190           0 :                 cp = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
     191           0 :                 aiov.iov_base = cp;
     192           0 :                 aiov.iov_len = MAXPATHLEN;
     193           0 :                 auio.uio_iov = &aiov;
     194           0 :                 auio.uio_iovcnt = 1;
     195           0 :                 auio.uio_offset = 0;
     196           0 :                 auio.uio_rw = UIO_READ;
     197           0 :                 auio.uio_segflg = UIO_SYSSPACE;
     198           0 :                 auio.uio_procp = ap->a_p;
     199           0 :                 auio.uio_resid = MAXPATHLEN;
     200           0 :                 rdlnk.a_uio = &auio;
     201           0 :                 rdlnk.a_vp = ap->a_vp;
     202           0 :                 rdlnk.a_cred = ap->a_cred;
     203           0 :                 if (cd9660_readlink(&rdlnk) == 0)
     204           0 :                         vap->va_size = MAXPATHLEN - auio.uio_resid;
     205           0 :                 free(cp, M_TEMP, 0);
     206           0 :         }
     207           0 :         vap->va_flags        = 0;
     208           0 :         vap->va_gen = 1;
     209           0 :         vap->va_blocksize = ip->i_mnt->logical_block_size;
     210           0 :         vap->va_bytes        = (u_quad_t) ip->i_size;
     211           0 :         vap->va_type = vp->v_type;
     212           0 :         return (0);
     213             : }
     214             : 
     215             : /*
     216             :  * Vnode op for reading.
     217             :  */
     218             : int
     219           0 : cd9660_read(void *v)
     220             : {
     221           0 :         struct vop_read_args *ap = v;
     222           0 :         struct vnode *vp = ap->a_vp;
     223           0 :         register struct uio *uio = ap->a_uio;
     224           0 :         register struct iso_node *ip = VTOI(vp);
     225             :         register struct iso_mnt *imp;
     226           0 :         struct buf *bp;
     227             :         daddr_t lbn, rablock;
     228             :         off_t diff;
     229             :         int error = 0;
     230             :         long size, on;
     231             :         size_t n;
     232             : 
     233           0 :         if (uio->uio_resid == 0)
     234           0 :                 return (0);
     235           0 :         if (uio->uio_offset < 0)
     236           0 :                 return (EINVAL);
     237           0 :         ip->i_flag |= IN_ACCESS;
     238           0 :         imp = ip->i_mnt;
     239           0 :         do {
     240           0 :                 struct cluster_info *ci = &ip->i_ci;
     241             : 
     242           0 :                 lbn = lblkno(imp, uio->uio_offset);
     243           0 :                 on = blkoff(imp, uio->uio_offset);
     244           0 :                 n = ulmin(imp->logical_block_size - on, uio->uio_resid);
     245           0 :                 diff = (off_t)ip->i_size - uio->uio_offset;
     246           0 :                 if (diff <= 0)
     247           0 :                         return (0);
     248           0 :                 if (diff < n)
     249           0 :                         n = diff;
     250           0 :                 size = blksize(imp, ip, lbn);
     251           0 :                 rablock = lbn + 1;
     252             : #define MAX_RA 32
     253           0 :                 if (ci->ci_lastr + 1 == lbn) {
     254             :                         struct ra {
     255             :                                 daddr_t blks[MAX_RA];
     256             :                                 int sizes[MAX_RA];
     257             :                         } *ra;
     258             :                         int i;
     259             : 
     260           0 :                         ra = malloc(sizeof *ra, M_TEMP, M_WAITOK);
     261           0 :                         for (i = 0; i < MAX_RA &&
     262           0 :                             lblktosize(imp, (rablock + i)) < ip->i_size;
     263           0 :                             i++) {
     264           0 :                                 ra->blks[i] = rablock + i;
     265           0 :                                 ra->sizes[i] = blksize(imp, ip, rablock + i);
     266             :                         }
     267           0 :                         error = breadn(vp, lbn, size, ra->blks,
     268           0 :                             ra->sizes, i, &bp);
     269           0 :                         free(ra, M_TEMP, 0);
     270           0 :                 } else
     271           0 :                         error = bread(vp, lbn, size, &bp);
     272           0 :                 ci->ci_lastr = lbn;
     273           0 :                 n = ulmin(n, size - bp->b_resid);
     274           0 :                 if (error) {
     275           0 :                         brelse(bp);
     276           0 :                         return (error);
     277             :                 }
     278             : 
     279           0 :                 error = uiomove(bp->b_data + on, n, uio);
     280             : 
     281           0 :                 brelse(bp);
     282           0 :         } while (error == 0 && uio->uio_resid > 0 && n != 0);
     283           0 :         return (error);
     284           0 : }
     285             : 
     286             : /* ARGSUSED */
     287             : int
     288           0 : cd9660_ioctl(void *v)
     289             : {
     290           0 :         return (ENOTTY);
     291             : }
     292             : 
     293             : /* ARGSUSED */
     294             : int
     295           0 : cd9660_poll(void *v)
     296             : {
     297           0 :         struct vop_poll_args *ap = v;
     298             : 
     299             :         /*
     300             :          * We should really check to see if I/O is possible.
     301             :          */
     302           0 :         return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
     303             : }
     304             : 
     305             : /*
     306             :  * Mmap a file
     307             :  *
     308             :  * NB Currently unsupported.
     309             :  */
     310             : /* ARGSUSED */
     311             : int
     312           0 : cd9660_mmap(void *v)
     313             : {
     314             : 
     315           0 :         return (EINVAL);
     316             : }
     317             : 
     318             : /*
     319             :  * Seek on a file
     320             :  *
     321             :  * Nothing to do, so just return.
     322             :  */
     323             : /* ARGSUSED */
     324             : int
     325           0 : cd9660_seek(void *v)
     326             : {
     327           0 :         return (0);
     328             : }
     329             : 
     330             : int
     331           0 : iso_uiodir(idp,dp,off)
     332             :         struct isoreaddir *idp;
     333             :         struct dirent *dp;
     334             :         off_t off;
     335             : {
     336             :         int error;
     337             : 
     338           0 :         dp->d_name[dp->d_namlen] = 0;
     339           0 :         dp->d_reclen = DIRENT_SIZE(dp);
     340             : 
     341           0 :         if (idp->uio->uio_resid < dp->d_reclen) {
     342           0 :                 idp->eofflag = 0;
     343           0 :                 return (-1);
     344             :         }
     345             : 
     346           0 :         dp->d_off = off;
     347           0 :         if ((error = uiomove(dp, dp->d_reclen, idp->uio)) != 0)
     348           0 :                 return (error);
     349           0 :         idp->uio_off = off;
     350           0 :         return (0);
     351           0 : }
     352             : 
     353             : int
     354           0 : iso_shipdir(idp)
     355             :         struct isoreaddir *idp;
     356             : {
     357             :         struct dirent *dp;
     358             :         int cl, sl, assoc;
     359             :         int error;
     360             :         char *cname, *sname;
     361             : 
     362           0 :         cl = idp->current.d_namlen;
     363           0 :         cname = idp->current.d_name;
     364             : 
     365           0 :         if ((assoc = cl > 1 && *cname == ASSOCCHAR)) {
     366           0 :                 cl--;
     367           0 :                 cname++;
     368           0 :         }
     369             : 
     370           0 :         dp = &idp->saveent;
     371           0 :         sname = dp->d_name;
     372           0 :         if (!(sl = dp->d_namlen)) {
     373           0 :                 dp = &idp->assocent;
     374           0 :                 sname = dp->d_name + 1;
     375           0 :                 sl = dp->d_namlen - 1;
     376           0 :         }
     377           0 :         if (sl > 0) {
     378           0 :                 if (sl != cl
     379           0 :                     || bcmp(sname,cname,sl)) {
     380           0 :                         if (idp->assocent.d_namlen) {
     381           0 :                                 error = iso_uiodir(idp, &idp->assocent,
     382           0 :                                                    idp->assocoff);
     383           0 :                                 if (error)
     384           0 :                                         return (error);
     385           0 :                                 idp->assocent.d_namlen = 0;
     386           0 :                         }
     387           0 :                         if (idp->saveent.d_namlen) {
     388           0 :                                 error = iso_uiodir(idp, &idp->saveent,
     389           0 :                                                    idp->saveoff);
     390           0 :                                 if (error)
     391           0 :                                         return (error);
     392           0 :                                 idp->saveent.d_namlen = 0;
     393           0 :                         }
     394             :                 }
     395             :         }
     396           0 :         idp->current.d_reclen = DIRENT_SIZE(&idp->current);
     397           0 :         if (assoc) {
     398           0 :                 idp->assocoff = idp->curroff;
     399           0 :                 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
     400           0 :         } else {
     401           0 :                 idp->saveoff = idp->curroff;
     402           0 :                 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
     403             :         }
     404           0 :         return (0);
     405           0 : }
     406             : 
     407             : /*
     408             :  * Vnode op for readdir
     409             :  */
     410             : int
     411           0 : cd9660_readdir(void *v)
     412             : {
     413           0 :         struct vop_readdir_args *ap = v;
     414           0 :         register struct uio *uio = ap->a_uio;
     415             :         struct isoreaddir *idp;
     416           0 :         struct vnode *vdp = ap->a_vp;
     417             :         struct iso_node *dp;
     418             :         struct iso_mnt *imp;
     419           0 :         struct buf *bp = NULL;
     420             :         struct iso_directory_record *ep;
     421             :         int entryoffsetinblock;
     422             :         doff_t endsearch;
     423             :         u_long bmask;
     424             :         int error = 0;
     425             :         int reclen;
     426           0 :         u_short namelen;
     427           0 :         cdino_t ino;
     428             : 
     429           0 :         dp = VTOI(vdp);
     430           0 :         imp = dp->i_mnt;
     431           0 :         bmask = imp->im_bmask;
     432             : 
     433           0 :         idp = malloc(sizeof(*idp), M_TEMP, M_WAITOK);
     434             : 
     435             :         /*
     436             :          * These are passed to copyout(), so make sure there's no garbage
     437             :          * being leaked in padding or after short names.
     438             :          */
     439           0 :         memset(&idp->saveent, 0, sizeof(idp->saveent));
     440           0 :         memset(&idp->assocent, 0, sizeof(idp->assocent));
     441           0 :         memset(&idp->current, 0, sizeof(idp->current));
     442             : 
     443             :         /*
     444             :          * XXX
     445             :          * Is it worth trying to figure out the type?
     446             :          */
     447           0 :         idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
     448             :             DT_UNKNOWN;
     449           0 :         idp->uio = uio;
     450           0 :         idp->eofflag = 1;
     451           0 :         idp->curroff = uio->uio_offset;
     452           0 :         idp->uio_off = uio->uio_offset;
     453             : 
     454           0 :         if ((entryoffsetinblock = idp->curroff & bmask) &&
     455           0 :             (error = cd9660_bufatoff(dp, (off_t)idp->curroff, NULL, &bp))) {
     456           0 :                 free(idp, M_TEMP, 0);
     457           0 :                 return (error);
     458             :         }
     459           0 :         endsearch = dp->i_size;
     460             : 
     461           0 :         while (idp->curroff < endsearch) {
     462             :                 /*
     463             :                  * If offset is on a block boundary,
     464             :                  * read the next directory block.
     465             :                  * Release previous if it exists.
     466             :                  */
     467           0 :                 if ((idp->curroff & bmask) == 0) {
     468           0 :                         if (bp != NULL)
     469           0 :                                 brelse(bp);
     470           0 :                         error = cd9660_bufatoff(dp, (off_t)idp->curroff,
     471             :                                              NULL, &bp);
     472           0 :                         if (error)
     473             :                                 break;
     474             :                         entryoffsetinblock = 0;
     475           0 :                 }
     476             :                 /*
     477             :                  * Get pointer to next entry.
     478             :                  */
     479           0 :                 ep = (struct iso_directory_record *)
     480           0 :                         ((char *)bp->b_data + entryoffsetinblock);
     481             : 
     482           0 :                 reclen = isonum_711(ep->length);
     483           0 :                 if (reclen == 0) {
     484             :                         /* skip to next block, if any */
     485           0 :                         idp->curroff =
     486           0 :                             (idp->curroff & ~bmask) + imp->logical_block_size;
     487           0 :                         continue;
     488             :                 }
     489             : 
     490           0 :                 if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
     491             :                         error = EINVAL;
     492             :                         /* illegal entry, stop */
     493           0 :                         break;
     494             :                 }
     495             : 
     496           0 :                 if (entryoffsetinblock + reclen > imp->logical_block_size) {
     497             :                         error = EINVAL;
     498             :                         /* illegal directory, so stop looking */
     499           0 :                         break;
     500             :                 }
     501             : 
     502           0 :                 idp->current.d_namlen = isonum_711(ep->name_len);
     503             : 
     504           0 :                 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
     505             :                         error = EINVAL;
     506             :                         /* illegal entry, stop */
     507           0 :                         break;
     508             :                 }
     509             : 
     510           0 :                 if (isonum_711(ep->flags)&2)
     511           0 :                         ino = isodirino(ep, imp);
     512             :                 else
     513           0 :                         ino = dbtob(bp->b_blkno) + entryoffsetinblock;
     514             : 
     515           0 :                 idp->curroff += reclen;
     516             : 
     517           0 :                 switch (imp->iso_ftype) {
     518             :                 case ISO_FTYPE_RRIP:
     519           0 :                         cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
     520             :                                            &ino, imp);
     521           0 :                         idp->current.d_fileno = ino;
     522           0 :                         idp->current.d_namlen = (u_char)namelen;
     523           0 :                         if (idp->current.d_namlen)
     524           0 :                                 error = iso_uiodir(idp,&idp->current,idp->curroff);
     525             :                         break;
     526             :                 default:        /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
     527           0 :                         idp->current.d_fileno = ino;
     528           0 :                         strlcpy(idp->current.d_name,"..",
     529             :                             sizeof idp->current.d_name);
     530           0 :                         if (idp->current.d_namlen == 1 && ep->name[0] == 0) {
     531           0 :                                 idp->current.d_namlen = 1;
     532           0 :                                 error = iso_uiodir(idp,&idp->current,idp->curroff);
     533           0 :                         } else if (idp->current.d_namlen == 1 && 
     534           0 :                             ep->name[0] == 1) {
     535           0 :                                 idp->current.d_namlen = 2;
     536           0 :                                 error = iso_uiodir(idp,&idp->current,idp->curroff);
     537           0 :                         } else {
     538           0 :                                 isofntrans(ep->name,idp->current.d_namlen,
     539             :                                            idp->current.d_name, &namelen,
     540           0 :                                            imp->iso_ftype == ISO_FTYPE_9660,
     541           0 :                                            isonum_711(ep->flags) & 4,
     542           0 :                                            imp->joliet_level);
     543           0 :                                 idp->current.d_namlen = (u_char)namelen;
     544           0 :                                 if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
     545           0 :                                         error = iso_shipdir(idp);
     546             :                                 else
     547           0 :                                         error = iso_uiodir(idp,&idp->current,idp->curroff);
     548             :                         }
     549             :                 }
     550           0 :                 if (error)
     551             :                         break;
     552             : 
     553             :                 entryoffsetinblock += reclen;
     554             :         }
     555             : 
     556           0 :         if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
     557           0 :                 idp->current.d_namlen = 0;
     558           0 :                 error = iso_shipdir(idp);
     559           0 :         }
     560           0 :         if (error < 0)
     561           0 :                 error = 0;
     562             : 
     563           0 :         if (bp)
     564           0 :                 brelse (bp);
     565             : 
     566           0 :         uio->uio_offset = idp->uio_off;
     567           0 :         *ap->a_eofflag = idp->eofflag;
     568             : 
     569           0 :         free(idp, M_TEMP, 0);
     570             : 
     571           0 :         return (error);
     572           0 : }
     573             : 
     574             : /*
     575             :  * Return target name of a symbolic link
     576             :  * Shouldn't we get the parent vnode and read the data from there?
     577             :  * This could eventually result in deadlocks in cd9660_lookup.
     578             :  * But otherwise the block read here is in the block buffer two times.
     579             :  */
     580             : typedef struct iso_directory_record ISODIR;
     581             : typedef struct iso_node             ISONODE;
     582             : typedef struct iso_mnt              ISOMNT;
     583             : int
     584           0 : cd9660_readlink(void *v)
     585             : {
     586           0 :         struct vop_readlink_args *ap = v;
     587             :         ISONODE *ip;
     588             :         ISODIR  *dirp;
     589             :         ISOMNT  *imp;
     590           0 :         struct  buf *bp;
     591             :         struct  uio *uio;
     592           0 :         u_short symlen;
     593             :         int     error;
     594             :         char    *symname;
     595             : 
     596           0 :         ip  = VTOI(ap->a_vp);
     597           0 :         imp = ip->i_mnt;
     598           0 :         uio = ap->a_uio;
     599             : 
     600           0 :         if (imp->iso_ftype != ISO_FTYPE_RRIP)
     601           0 :                 return (EINVAL);
     602             : 
     603             :         /*
     604             :          * Get parents directory record block that this inode included.
     605             :          */
     606           0 :         error = bread(imp->im_devvp,
     607           0 :                       (ip->i_number >> imp->im_bshift) <<
     608           0 :                       (imp->im_bshift - DEV_BSHIFT),
     609           0 :                       imp->logical_block_size, &bp);
     610           0 :         if (error) {
     611           0 :                 brelse(bp);
     612           0 :                 return (EINVAL);
     613             :         }
     614             : 
     615             :         /*
     616             :          * Setup the directory pointer for this inode
     617             :          */
     618           0 :         dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
     619             : 
     620             :         /*
     621             :          * Just make sure, we have a right one....
     622             :          *   1: Check not cross boundary on block
     623             :          */
     624           0 :         if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
     625           0 :             > imp->logical_block_size) {
     626           0 :                 brelse(bp);
     627           0 :                 return (EINVAL);
     628             :         }
     629             : 
     630             :         /*
     631             :          * Now get a buffer
     632             :          * Abuse a namei buffer for now.
     633             :          */
     634           0 :         if (uio->uio_segflg == UIO_SYSSPACE &&
     635           0 :             uio->uio_iov->iov_len >= MAXPATHLEN)
     636           0 :                 symname = uio->uio_iov->iov_base;
     637             :         else
     638           0 :                 symname = pool_get(&namei_pool, PR_WAITOK);
     639             :         
     640             :         /*
     641             :          * Ok, we just gathering a symbolic name in SL record.
     642             :          */
     643           0 :         if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
     644           0 :                 if (uio->uio_segflg != UIO_SYSSPACE ||
     645           0 :                     uio->uio_iov->iov_len < MAXPATHLEN)
     646           0 :                         pool_put(&namei_pool, symname);
     647           0 :                 brelse(bp);
     648           0 :                 return (EINVAL);
     649             :         }
     650             :         /*
     651             :          * Don't forget before you leave from home ;-)
     652             :          */
     653           0 :         brelse(bp);
     654             : 
     655             :         /*
     656             :          * return with the symbolic name to caller's.
     657             :          */
     658           0 :         if (uio->uio_segflg != UIO_SYSSPACE ||
     659           0 :             uio->uio_iov->iov_len < MAXPATHLEN) {
     660           0 :                 error = uiomove(symname, symlen, uio);
     661           0 :                 pool_put(&namei_pool, symname);
     662           0 :                 return (error);
     663             :         }
     664           0 :         uio->uio_resid -= symlen;
     665           0 :         uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen;
     666           0 :         uio->uio_iov->iov_len -= symlen;
     667           0 :         return (0);
     668           0 : }
     669             : 
     670             : int
     671           0 : cd9660_link(void *v)
     672             : {
     673           0 :         struct vop_link_args *ap = v;
     674             : 
     675           0 :         VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
     676           0 :         vput(ap->a_dvp);
     677           0 :         return (EROFS);
     678             : }
     679             : 
     680             : int
     681           0 : cd9660_symlink(void *v)
     682             : {
     683           0 :         struct vop_symlink_args *ap = v;
     684             : 
     685           0 :         VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
     686           0 :         vput(ap->a_dvp);
     687           0 :         return (EROFS);
     688             : }
     689             : 
     690             : /*
     691             :  * Lock an inode.
     692             :  */
     693             : int
     694           0 : cd9660_lock(void *v)
     695             : {
     696           0 :         struct vop_lock_args *ap = v;
     697           0 :         struct vnode *vp = ap->a_vp;
     698             : 
     699           0 :         return rrw_enter(&VTOI(vp)->i_lock, ap->a_flags & LK_RWFLAGS);
     700             : }
     701             : 
     702             : /*
     703             :  * Unlock an inode.
     704             :  */
     705             : int
     706           0 : cd9660_unlock(void *v)
     707             : {
     708           0 :         struct vop_unlock_args *ap = v;
     709           0 :         struct vnode *vp = ap->a_vp;
     710             : 
     711           0 :         rrw_exit(&VTOI(vp)->i_lock);
     712           0 :         return 0;
     713             : }
     714             : 
     715             : /*
     716             :  * Calculate the logical to physical mapping if not done already,
     717             :  * then call the device strategy routine.
     718             :  */
     719             : int
     720           0 : cd9660_strategy(void *v)
     721             : {
     722           0 :         struct vop_strategy_args *ap = v;
     723           0 :         struct buf *bp = ap->a_bp;
     724           0 :         struct vnode *vp = bp->b_vp;
     725             :         struct iso_node *ip;
     726             :         int error;
     727             :         int s;
     728             : 
     729           0 :         ip = VTOI(vp);
     730           0 :         if (vp->v_type == VBLK || vp->v_type == VCHR)
     731           0 :                 panic("cd9660_strategy: spec");
     732           0 :         if (bp->b_blkno == bp->b_lblkno) {
     733           0 :                 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
     734           0 :                 if (error) {
     735           0 :                         bp->b_error = error;
     736           0 :                         bp->b_flags |= B_ERROR;
     737           0 :                         s = splbio();
     738           0 :                         biodone(bp);
     739           0 :                         splx(s);
     740           0 :                         return (error);
     741             :                 }
     742           0 :                 if ((long)bp->b_blkno == -1)
     743           0 :                         clrbuf(bp);
     744             :         }
     745           0 :         if ((long)bp->b_blkno == -1) {
     746           0 :                 s = splbio();
     747           0 :                 biodone(bp);
     748           0 :                 splx(s);
     749           0 :                 return (0);
     750             :         }
     751           0 :         vp = ip->i_devvp;
     752           0 :         bp->b_dev = vp->v_rdev;
     753           0 :         (vp->v_op->vop_strategy)(ap);
     754           0 :         return (0);
     755           0 : }
     756             : 
     757             : /*
     758             :  * Print out the contents of an inode.
     759             :  */
     760             : /*ARGSUSED*/
     761             : int
     762           0 : cd9660_print(void *v)
     763             : {
     764           0 :         printf("tag VT_ISOFS, isofs vnode\n");
     765           0 :         return (0);
     766             : }
     767             : 
     768             : /*
     769             :  * Check for a locked inode.
     770             :  */
     771             : int
     772           0 : cd9660_islocked(void *v)
     773             : {
     774           0 :         struct vop_islocked_args *ap = v;
     775             : 
     776           0 :         return rrw_status(&VTOI(ap->a_vp)->i_lock);
     777             : }
     778             : 
     779             : /*
     780             :  * Return POSIX pathconf information applicable to cd9660 filesystems.
     781             :  */
     782             : int
     783           0 : cd9660_pathconf(void *v)
     784             : {
     785           0 :         struct vop_pathconf_args *ap = v;
     786             :         int error = 0;
     787             : 
     788           0 :         switch (ap->a_name) {
     789             :         case _PC_LINK_MAX:
     790           0 :                 *ap->a_retval = 1;
     791           0 :                 break;
     792             :         case _PC_NAME_MAX:
     793           0 :                 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
     794           0 :                         *ap->a_retval = NAME_MAX;
     795             :                 else
     796           0 :                         *ap->a_retval = 37;
     797             :                 break;
     798             :         case _PC_CHOWN_RESTRICTED:
     799           0 :                 *ap->a_retval = 1;
     800           0 :                 break;
     801             :         case _PC_NO_TRUNC:
     802           0 :                 *ap->a_retval = 1;
     803           0 :                 break;
     804             :         case _PC_TIMESTAMP_RESOLUTION:
     805           0 :                 *ap->a_retval = 1000000000;  /* one billion nanoseconds */
     806           0 :                 break;
     807             :         default:
     808             :                 error = EINVAL;
     809           0 :                 break;
     810             :         }
     811             : 
     812           0 :         return (error);
     813             : }
     814             : 
     815             : /*
     816             :  * Global vfs data structures for isofs
     817             :  */
     818             : #define cd9660_create   eopnotsupp
     819             : #define cd9660_mknod    eopnotsupp
     820             : #define cd9660_write    eopnotsupp
     821             : #define cd9660_fsync    nullop
     822             : #define cd9660_remove   eopnotsupp
     823             : #define cd9660_rename   eopnotsupp
     824             : #define cd9660_mkdir    eopnotsupp
     825             : #define cd9660_rmdir    eopnotsupp
     826             : #define cd9660_advlock  eopnotsupp
     827             : #define cd9660_valloc   eopnotsupp
     828             : #define cd9660_vfree    eopnotsupp
     829             : #define cd9660_truncate eopnotsupp
     830             : #define cd9660_update   eopnotsupp
     831             : #define cd9660_bwrite   eopnotsupp
     832             : #define cd9660_revoke   vop_generic_revoke
     833             : 
     834             : /* Global vfs data structures for cd9660. */
     835             : struct vops cd9660_vops = {
     836             :         .vop_lookup     = cd9660_lookup,
     837             :         .vop_create     = cd9660_create,
     838             :         .vop_mknod      = cd9660_mknod,
     839             :         .vop_open       = cd9660_open,
     840             :         .vop_close      = cd9660_close,
     841             :         .vop_access     = cd9660_access,
     842             :         .vop_getattr    = cd9660_getattr,
     843             :         .vop_setattr    = cd9660_setattr,
     844             :         .vop_read       = cd9660_read,
     845             :         .vop_write      = cd9660_write,
     846             :         .vop_ioctl      = cd9660_ioctl,
     847             :         .vop_poll       = cd9660_poll,
     848             :         .vop_kqfilter   = cd9660_kqfilter,
     849             :         .vop_revoke     = cd9660_revoke,
     850             :         .vop_fsync      = cd9660_fsync,
     851             :         .vop_remove     = cd9660_remove,
     852             :         .vop_link       = cd9660_link,
     853             :         .vop_rename     = cd9660_rename,
     854             :         .vop_mkdir      = cd9660_mkdir,
     855             :         .vop_rmdir      = cd9660_rmdir,
     856             :         .vop_symlink    = cd9660_symlink,
     857             :         .vop_readdir    = cd9660_readdir,
     858             :         .vop_readlink   = cd9660_readlink,
     859             :         .vop_abortop    = vop_generic_abortop,
     860             :         .vop_inactive   = cd9660_inactive,
     861             :         .vop_reclaim    = cd9660_reclaim,
     862             :         .vop_lock       = cd9660_lock,
     863             :         .vop_unlock     = cd9660_unlock,
     864             :         .vop_bmap       = cd9660_bmap,
     865             :         .vop_strategy   = cd9660_strategy,
     866             :         .vop_print      = cd9660_print,
     867             :         .vop_islocked   = cd9660_islocked,
     868             :         .vop_pathconf   = cd9660_pathconf,
     869             :         .vop_advlock    = cd9660_advlock,
     870             :         .vop_bwrite     = vop_generic_bwrite
     871             : };
     872             : 
     873             : /* Special device vnode ops */
     874             : struct vops cd9660_specvops = {
     875             :         .vop_access     = cd9660_access,
     876             :         .vop_getattr    = cd9660_getattr,
     877             :         .vop_setattr    = cd9660_setattr,
     878             :         .vop_inactive   = cd9660_inactive,
     879             :         .vop_reclaim    = cd9660_reclaim,
     880             :         .vop_lock       = cd9660_lock,
     881             :         .vop_unlock     = cd9660_unlock,
     882             :         .vop_print      = cd9660_print,
     883             :         .vop_islocked   = cd9660_islocked,
     884             : 
     885             :         /* XXX: Keep in sync with spec_vops. */
     886             :         .vop_lookup     = vop_generic_lookup,
     887             :         .vop_create     = spec_badop,
     888             :         .vop_mknod      = spec_badop,
     889             :         .vop_open       = spec_open,
     890             :         .vop_close      = spec_close,
     891             :         .vop_read       = spec_read,
     892             :         .vop_write      = spec_write,
     893             :         .vop_ioctl      = spec_ioctl,
     894             :         .vop_poll       = spec_poll,
     895             :         .vop_kqfilter   = spec_kqfilter,
     896             :         .vop_revoke     = vop_generic_revoke,
     897             :         .vop_fsync      = spec_fsync,
     898             :         .vop_remove     = spec_badop,
     899             :         .vop_link       = spec_badop,
     900             :         .vop_rename     = spec_badop,
     901             :         .vop_mkdir      = spec_badop,
     902             :         .vop_rmdir      = spec_badop,
     903             :         .vop_symlink    = spec_badop,
     904             :         .vop_readdir    = spec_badop,
     905             :         .vop_readlink   = spec_badop,
     906             :         .vop_abortop    = spec_badop,
     907             :         .vop_bmap       = vop_generic_bmap,
     908             :         .vop_strategy   = spec_strategy,
     909             :         .vop_pathconf   = spec_pathconf,
     910             :         .vop_advlock    = spec_advlock,
     911             :         .vop_bwrite     = vop_generic_bwrite,
     912             : };
     913             : 
     914             : #ifdef FIFO
     915             : struct vops cd9660_fifovops = {
     916             :         .vop_access     = cd9660_access,
     917             :         .vop_getattr    = cd9660_getattr,
     918             :         .vop_setattr    = cd9660_setattr,
     919             :         .vop_inactive   = cd9660_inactive,
     920             :         .vop_reclaim    = cd9660_reclaim,
     921             :         .vop_lock       = cd9660_lock,
     922             :         .vop_unlock     = cd9660_unlock,
     923             :         .vop_print      = cd9660_print,
     924             :         .vop_islocked   = cd9660_islocked,
     925             :         .vop_bwrite     = vop_generic_bwrite,
     926             : 
     927             :         /* XXX: Keep in sync with fifo_vops. */
     928             :         .vop_lookup     = vop_generic_lookup,
     929             :         .vop_create     = fifo_badop,
     930             :         .vop_mknod      = fifo_badop,
     931             :         .vop_open       = fifo_open,
     932             :         .vop_close      = fifo_close,
     933             :         .vop_read       = fifo_read,
     934             :         .vop_write      = fifo_write,
     935             :         .vop_ioctl      = fifo_ioctl,
     936             :         .vop_poll       = fifo_poll,
     937             :         .vop_kqfilter   = fifo_kqfilter,
     938             :         .vop_revoke     = vop_generic_revoke,
     939             :         .vop_fsync      = nullop,
     940             :         .vop_remove     = fifo_badop,
     941             :         .vop_link       = fifo_badop,
     942             :         .vop_rename     = fifo_badop,
     943             :         .vop_mkdir      = fifo_badop,
     944             :         .vop_rmdir      = fifo_badop,
     945             :         .vop_symlink    = fifo_badop,
     946             :         .vop_readdir    = fifo_badop,
     947             :         .vop_readlink   = fifo_badop,
     948             :         .vop_abortop    = fifo_badop,
     949             :         .vop_bmap       = vop_generic_bmap,
     950             :         .vop_strategy   = fifo_badop,
     951             :         .vop_pathconf   = fifo_pathconf,
     952             :         .vop_advlock    = fifo_advlock,
     953             : };
     954             : #endif /* FIFO */
     955             : 
     956             : void filt_cd9660detach(struct knote *kn);
     957             : int filt_cd9660read(struct knote *kn, long hint);
     958             : int filt_cd9660write(struct knote *kn, long hint);
     959             : int filt_cd9660vnode(struct knote *kn, long hint);
     960             : 
     961             : struct filterops cd9660read_filtops = 
     962             :         { 1, NULL, filt_cd9660detach, filt_cd9660read };
     963             : struct filterops cd9660write_filtops = 
     964             :         { 1, NULL, filt_cd9660detach, filt_cd9660write };
     965             : struct filterops cd9660vnode_filtops = 
     966             :         { 1, NULL, filt_cd9660detach, filt_cd9660vnode };
     967             : 
     968             : int
     969           0 : cd9660_kqfilter(void *v)
     970             : {
     971           0 :         struct vop_kqfilter_args *ap = v;
     972           0 :         struct vnode *vp = ap->a_vp;
     973           0 :         struct knote *kn = ap->a_kn;
     974             : 
     975           0 :         switch (kn->kn_filter) {
     976             :         case EVFILT_READ:
     977           0 :                 kn->kn_fop = &cd9660read_filtops;
     978           0 :                 break;
     979             :         case EVFILT_WRITE:
     980           0 :                 kn->kn_fop = &cd9660write_filtops;
     981           0 :                 break;
     982             :         case EVFILT_VNODE:
     983           0 :                 kn->kn_fop = &cd9660vnode_filtops;
     984           0 :                 break;
     985             :         default:
     986           0 :                 return (EINVAL);
     987             :         }
     988             : 
     989           0 :         kn->kn_hook = (caddr_t)vp;
     990             : 
     991           0 :         SLIST_INSERT_HEAD(&vp->v_selectinfo.si_note, kn, kn_selnext);
     992             : 
     993           0 :         return (0);
     994           0 : }
     995             : 
     996             : void
     997           0 : filt_cd9660detach(struct knote *kn)
     998             : {
     999           0 :         struct vnode *vp = (struct vnode *)kn->kn_hook;
    1000             : 
    1001           0 :         SLIST_REMOVE(&vp->v_selectinfo.si_note, kn, knote, kn_selnext);
    1002           0 : }
    1003             : 
    1004             : int
    1005           0 : filt_cd9660read(struct knote *kn, long hint)
    1006             : {
    1007           0 :         struct vnode *vp = (struct vnode *)kn->kn_hook;
    1008           0 :         struct iso_node *node = VTOI(vp);
    1009             : 
    1010             :         /*
    1011             :          * filesystem is gone, so set the EOF flag and schedule 
    1012             :          * the knote for deletion.
    1013             :          */
    1014           0 :         if (hint == NOTE_REVOKE) {
    1015           0 :                 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
    1016           0 :                 return (1);
    1017             :         }
    1018             : 
    1019           0 :         kn->kn_data = node->i_size - kn->kn_fp->f_offset;
    1020           0 :         if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) {
    1021           0 :                 kn->kn_fflags |= NOTE_EOF;
    1022           0 :                 return (1);
    1023             :         }
    1024             : 
    1025           0 :         return (kn->kn_data != 0);
    1026           0 : }
    1027             : 
    1028             : int
    1029           0 : filt_cd9660write(struct knote *kn, long hint)
    1030             : {
    1031             :         /*
    1032             :          * filesystem is gone, so set the EOF flag and schedule 
    1033             :          * the knote for deletion.
    1034             :          */
    1035           0 :         if (hint == NOTE_REVOKE) {
    1036           0 :                 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
    1037           0 :                 return (1);
    1038             :         }
    1039             : 
    1040           0 :         kn->kn_data = 0;
    1041           0 :         return (1);
    1042           0 : }
    1043             : 
    1044             : int
    1045           0 : filt_cd9660vnode(struct knote *kn, long hint)
    1046             : {
    1047           0 :         if (kn->kn_sfflags & hint)
    1048           0 :                 kn->kn_fflags |= hint;
    1049           0 :         if (hint == NOTE_REVOKE) {
    1050           0 :                 kn->kn_flags |= EV_EOF;
    1051           0 :                 return (1);
    1052             :         }
    1053           0 :         return (kn->kn_fflags != 0);
    1054           0 : }

Generated by: LCOV version 1.13