The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/cd9660/cd9660_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: cd9660_vnops.c,v 1.8 2004/01/26 10:39:30 hannken Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1994
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley
    8  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
    9  * Support code is derived from software contributed to Berkeley
   10  * by Atsushi Murai (amurai@spec.co.jp).
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)cd9660_vnops.c      8.15 (Berkeley) 5/27/95
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.8 2004/01/26 10:39:30 hannken Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/namei.h>
   45 #include <sys/resourcevar.h>
   46 #include <sys/kernel.h>
   47 #include <sys/file.h>
   48 #include <sys/stat.h>
   49 #include <sys/buf.h>
   50 #include <sys/proc.h>
   51 #include <sys/mount.h>
   52 #include <sys/vnode.h>
   53 #include <sys/malloc.h>
   54 #include <sys/dirent.h>
   55 
   56 #include <miscfs/fifofs/fifo.h>
   57 #include <miscfs/genfs/genfs.h>
   58 #include <miscfs/specfs/specdev.h>
   59 
   60 #include <fs/cd9660/iso.h>
   61 #include <fs/cd9660/cd9660_extern.h>
   62 #include <fs/cd9660/cd9660_node.h>
   63 #include <fs/cd9660/iso_rrip.h>
   64 #include <fs/cd9660/cd9660_mount.h>
   65 
   66 /*
   67  * Structure for reading directories
   68  */
   69 struct isoreaddir {
   70         struct dirent saveent;
   71         struct dirent assocent;
   72         struct dirent current;
   73         off_t saveoff;
   74         off_t assocoff;
   75         off_t curroff;
   76         struct uio *uio;
   77         off_t uio_off;
   78         int eofflag;
   79         off_t *cookies;
   80         int ncookies;
   81 };
   82 
   83 int     iso_uiodir __P((struct isoreaddir *, struct dirent *, off_t));
   84 int     iso_shipdir __P((struct isoreaddir *));
   85 
   86 #if 0
   87 /*
   88  * Mknod vnode call
   89  *  Actually remap the device number
   90  */
   91 int
   92 cd9660_mknod(ndp, vap, cred, p)
   93         struct nameidata *ndp;
   94         struct ucred *cred;
   95         struct vattr *vap;
   96         struct proc *p;
   97 {
   98 #ifndef ISODEVMAP
   99         free(ndp->ni_pnbuf, M_NAMEI);
  100         vput(ndp->ni_dvp);
  101         vput(ndp->ni_vp);
  102         return (EINVAL);
  103 #else
  104         struct vnode *vp;
  105         struct iso_node *ip;
  106         struct iso_dnode *dp;
  107 
  108         vp = ndp->ni_vp;
  109         ip = VTOI(vp);
  110 
  111         if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
  112             || vap->va_type != vp->v_type
  113             || (vap->va_type != VCHR && vap->va_type != VBLK)) {
  114                 free(ndp->ni_pnbuf, M_NAMEI);
  115                 vput(ndp->ni_dvp);
  116                 vput(ndp->ni_vp);
  117                 return (EINVAL);
  118         }
  119 
  120         dp = iso_dmap(ip->i_dev, ip->i_number, 1);
  121         if (ip->inode.iso_rdev == vap->va_rdev ||
  122             vap->va_rdev == (dev_t)VNOVAL) {
  123                 /* same as the unmapped one, delete the mapping */
  124                 LIST_REMOVE(dp, d_hash);
  125                 FREE(dp, M_CACHE);
  126         } else
  127                 /* enter new mapping */
  128                 dp->d_dev = vap->va_rdev;
  129 
  130         /*
  131          * Remove inode so that it will be reloaded by iget and
  132          * checked to see if it is an alias of an existing entry
  133          * in the inode cache.
  134          */
  135         vput(vp);
  136         vp->v_type = VNON;
  137         vgone(vp);
  138         return (0);
  139 #endif
  140 }
  141 #endif
  142 
  143 /*
  144  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
  145  * The mode is shifted to select the owner/group/other fields. The
  146  * super user is granted all permissions.
  147  */
  148 int
  149 cd9660_access(v)
  150         void *v;
  151 {
  152         struct vop_access_args /* {
  153                 struct vnode *a_vp;
  154                 int  a_mode;
  155                 struct ucred *a_cred;
  156                 struct proc *a_p;
  157         } */ *ap = v;
  158         struct vnode *vp = ap->a_vp;
  159         struct iso_node *ip = VTOI(vp);
  160 
  161         /*
  162          * Disallow write attempts unless the file is a socket,
  163          * fifo, or a block or character device resident on the
  164          * file system.
  165          */
  166         if (ap->a_mode & VWRITE) {
  167                 switch (vp->v_type) {
  168                 case VDIR:
  169                 case VLNK:
  170                 case VREG:
  171                         return (EROFS);
  172                 default:
  173                         break;
  174                 }
  175         }
  176 
  177         return (vaccess(vp->v_type, ip->inode.iso_mode & ALLPERMS,
  178             ip->inode.iso_uid, ip->inode.iso_gid, ap->a_mode, ap->a_cred));
  179 }
  180 
  181 int
  182 cd9660_getattr(v)
  183         void *v;
  184 {
  185         struct vop_getattr_args /* {
  186                 struct vnode *a_vp;
  187                 struct vattr *a_vap;
  188                 struct ucred *a_cred;
  189                 struct proc *a_p;
  190         } */ *ap = v;
  191         struct vnode *vp = ap->a_vp;
  192         struct iso_node *ip = VTOI(vp);
  193         struct vattr *vap = ap->a_vap;
  194 
  195         vap->va_fsid    = ip->i_dev;
  196         vap->va_fileid  = ip->i_number;
  197 
  198         vap->va_mode    = ip->inode.iso_mode & ALLPERMS;
  199         vap->va_nlink   = ip->inode.iso_links;
  200         vap->va_uid     = ip->inode.iso_uid;
  201         vap->va_gid     = ip->inode.iso_gid;
  202         vap->va_atime   = ip->inode.iso_atime;
  203         vap->va_mtime   = ip->inode.iso_mtime;
  204         vap->va_ctime   = ip->inode.iso_ctime;
  205         vap->va_rdev    = ip->inode.iso_rdev;
  206 
  207         vap->va_size    = (u_quad_t) ip->i_size;
  208         if (ip->i_size == 0 && vp->v_type == VLNK) {
  209                 struct vop_readlink_args rdlnk;
  210                 struct iovec aiov;
  211                 struct uio auio;
  212                 char *cp;
  213 
  214                 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
  215                 aiov.iov_base = cp;
  216                 aiov.iov_len = MAXPATHLEN;
  217                 auio.uio_iov = &aiov;
  218                 auio.uio_iovcnt = 1;
  219                 auio.uio_offset = 0;
  220                 auio.uio_rw = UIO_READ;
  221                 auio.uio_segflg = UIO_SYSSPACE;
  222                 auio.uio_procp = ap->a_p;
  223                 auio.uio_resid = MAXPATHLEN;
  224                 rdlnk.a_uio = &auio;
  225                 rdlnk.a_vp = ap->a_vp;
  226                 rdlnk.a_cred = ap->a_cred;
  227                 if (cd9660_readlink(&rdlnk) == 0)
  228                         vap->va_size = MAXPATHLEN - auio.uio_resid;
  229                 FREE(cp, M_TEMP);
  230         }
  231         vap->va_flags   = 0;
  232         vap->va_gen = 1;
  233         vap->va_blocksize = ip->i_mnt->logical_block_size;
  234         vap->va_bytes   = (u_quad_t) ip->i_size;
  235         vap->va_type    = vp->v_type;
  236         return (0);
  237 }
  238 
  239 /*
  240  * Vnode op for reading.
  241  */
  242 int
  243 cd9660_read(v)
  244         void *v;
  245 {
  246         struct vop_read_args /* {
  247                 struct vnode *a_vp;
  248                 struct uio *a_uio;
  249                 int a_ioflag;
  250                 struct ucred *a_cred;
  251         } */ *ap = v;
  252         struct vnode *vp = ap->a_vp;
  253         struct uio *uio = ap->a_uio;
  254         struct iso_node *ip = VTOI(vp);
  255         struct iso_mnt *imp;
  256         struct buf *bp;
  257         daddr_t lbn, rablock;
  258         off_t diff;
  259         int rasize, error = 0;
  260         long size, n, on;
  261 
  262         if (uio->uio_resid == 0)
  263                 return (0);
  264         if (uio->uio_offset < 0)
  265                 return (EINVAL);
  266         if (uio->uio_offset >= ip->i_size)
  267                 return 0;
  268         ip->i_flag |= IN_ACCESS;
  269         imp = ip->i_mnt;
  270 
  271         if (vp->v_type == VREG) {
  272                 error = 0;
  273                 while (uio->uio_resid > 0) {
  274                         void *win;
  275                         vsize_t bytelen = MIN(ip->i_size - uio->uio_offset,
  276                                               uio->uio_resid);
  277 
  278                         if (bytelen == 0)
  279                                 break;
  280                         win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
  281                                         &bytelen, UBC_READ);
  282                         error = uiomove(win, bytelen, uio);
  283                         ubc_release(win, 0);
  284                         if (error)
  285                                 break;
  286                 }
  287                 goto out;
  288         }
  289 
  290         do {
  291                 lbn = lblkno(imp, uio->uio_offset);
  292                 on = blkoff(imp, uio->uio_offset);
  293                 n = MIN(imp->logical_block_size - on, uio->uio_resid);
  294                 diff = (off_t)ip->i_size - uio->uio_offset;
  295                 if (diff <= 0)
  296                         return (0);
  297                 if (diff < n)
  298                         n = diff;
  299                 size = blksize(imp, ip, lbn);
  300                 rablock = lbn + 1;
  301                 if (lblktosize(imp, rablock) < ip->i_size) {
  302                         rasize = blksize(imp, ip, rablock);
  303                         error = breadn(vp, lbn, size, &rablock,
  304                                        &rasize, 1, NOCRED, &bp);
  305                 } else {
  306                         error = bread(vp, lbn, size, NOCRED, &bp);
  307                 }
  308                 n = MIN(n, size - bp->b_resid);
  309                 if (error) {
  310                         brelse(bp);
  311                         return (error);
  312                 }
  313 
  314                 error = uiomove(bp->b_data + on, (int)n, uio);
  315                 brelse(bp);
  316         } while (error == 0 && uio->uio_resid > 0 && n != 0);
  317 
  318 out:
  319         return (error);
  320 }
  321 
  322 int
  323 iso_uiodir(idp, dp, off)
  324         struct isoreaddir *idp;
  325         struct dirent *dp;
  326         off_t off;
  327 {
  328         int error;
  329 
  330         dp->d_name[dp->d_namlen] = 0;
  331         dp->d_reclen = DIRENT_SIZE(dp);
  332 
  333         if (idp->uio->uio_resid < dp->d_reclen) {
  334                 idp->eofflag = 0;
  335                 return (-1);
  336         }
  337 
  338         if (idp->cookies) {
  339                 if (idp->ncookies <= 0) {
  340                         idp->eofflag = 0;
  341                         return (-1);
  342                 }
  343 
  344                 *idp->cookies++ = off;
  345                 --idp->ncookies;
  346         }
  347 
  348         if ((error = uiomove((caddr_t)dp, dp->d_reclen, idp->uio)) != 0)
  349                 return (error);
  350         idp->uio_off = off;
  351         return (0);
  352 }
  353 
  354 int
  355 iso_shipdir(idp)
  356         struct isoreaddir *idp;
  357 {
  358         struct dirent *dp;
  359         int cl, sl, assoc;
  360         int error;
  361         char *cname, *sname;
  362 
  363         cl = idp->current.d_namlen;
  364         cname = idp->current.d_name;
  365 
  366         if ((assoc = cl > 1 && *cname == ASSOCCHAR)) {
  367                 cl--;
  368                 cname++;
  369         }
  370 
  371         dp = &idp->saveent;
  372         sname = dp->d_name;
  373         if (!(sl = dp->d_namlen)) {
  374                 dp = &idp->assocent;
  375                 sname = dp->d_name + 1;
  376                 sl = dp->d_namlen - 1;
  377         }
  378         if (sl > 0) {
  379                 if (sl != cl
  380                     || memcmp(sname, cname, sl)) {
  381                         if (idp->assocent.d_namlen) {
  382                                 error = iso_uiodir(idp, &idp->assocent,
  383                                                    idp->assocoff);
  384                                 if (error)
  385                                         return (error);
  386                                 idp->assocent.d_namlen = 0;
  387                         }
  388                         if (idp->saveent.d_namlen) {
  389                                 error = iso_uiodir(idp, &idp->saveent,
  390                                                    idp->saveoff);
  391                                 if (error)
  392                                         return (error);
  393                                 idp->saveent.d_namlen = 0;
  394                         }
  395                 }
  396         }
  397         idp->current.d_reclen = DIRENT_SIZE(&idp->current);
  398         if (assoc) {
  399                 idp->assocoff = idp->curroff;
  400                 memcpy(&idp->assocent, &idp->current, idp->current.d_reclen);
  401         } else {
  402                 idp->saveoff = idp->curroff;
  403                 memcpy(&idp->saveent, &idp->current, idp->current.d_reclen);
  404         }
  405         return (0);
  406 }
  407 
  408 /*
  409  * Vnode op for readdir
  410  */
  411 int
  412 cd9660_readdir(v)
  413         void *v;
  414 {
  415         struct vop_readdir_args /* {
  416                 struct vnode *a_vp;
  417                 struct uio *a_uio;
  418                 struct ucred *a_cred;
  419                 int *a_eofflag;
  420                 off_t **a_cookies;
  421                 int *a_ncookies;
  422         } */ *ap = v;
  423         struct uio *uio = ap->a_uio;
  424         struct isoreaddir *idp;
  425         struct vnode *vdp = ap->a_vp;
  426         struct iso_node *dp;
  427         struct iso_mnt *imp;
  428         struct buf *bp = NULL;
  429         struct iso_directory_record *ep;
  430         int entryoffsetinblock;
  431         doff_t endsearch;
  432         u_long bmask;
  433         int error = 0;
  434         int reclen;
  435         u_short namelen;
  436         off_t *cookies = NULL;
  437         int ncookies = 0;
  438 
  439         if (vdp->v_type != VDIR)
  440                 return (ENOTDIR);
  441 
  442         dp = VTOI(vdp);
  443         imp = dp->i_mnt;
  444         bmask = imp->im_bmask;
  445 
  446         MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
  447         idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
  448         /*
  449          * XXX
  450          * Is it worth trying to figure out the type?
  451          */
  452         idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
  453             DT_UNKNOWN;
  454         idp->uio = uio;
  455         if (ap->a_ncookies == NULL)
  456                 idp->cookies = NULL;
  457         else {
  458                 ncookies = uio->uio_resid / 16;
  459                 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
  460                 idp->cookies = cookies;
  461                 idp->ncookies = ncookies;
  462         }
  463         idp->eofflag = 1;
  464         idp->curroff = uio->uio_offset;
  465 
  466         if ((entryoffsetinblock = idp->curroff & bmask) &&
  467             (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
  468                 FREE(idp, M_TEMP);
  469                 return (error);
  470         }
  471         endsearch = dp->i_size;
  472 
  473         while (idp->curroff < endsearch) {
  474                 /*
  475                  * If offset is on a block boundary,
  476                  * read the next directory block.
  477                  * Release previous if it exists.
  478                  */
  479                 if ((idp->curroff & bmask) == 0) {
  480                         if (bp != NULL)
  481                                 brelse(bp);
  482                         error = VOP_BLKATOFF(vdp, (off_t)idp->curroff,
  483                                              NULL, &bp);
  484                         if (error)
  485                                 break;
  486                         entryoffsetinblock = 0;
  487                 }
  488                 /*
  489                  * Get pointer to next entry.
  490                  */
  491                 ep = (struct iso_directory_record *)
  492                         ((char *)bp->b_data + entryoffsetinblock);
  493 
  494                 reclen = isonum_711(ep->length);
  495                 if (reclen == 0) {
  496                         /* skip to next block, if any */
  497                         idp->curroff =
  498                             (idp->curroff & ~bmask) + imp->logical_block_size;
  499                         continue;
  500                 }
  501 
  502                 if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
  503                         error = EINVAL;
  504                         /* illegal entry, stop */
  505                         break;
  506                 }
  507 
  508                 if (entryoffsetinblock + reclen > imp->logical_block_size) {
  509                         error = EINVAL;
  510                         /* illegal directory, so stop looking */
  511                         break;
  512                 }
  513 
  514                 idp->current.d_namlen = isonum_711(ep->name_len);
  515 
  516                 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
  517                         error = EINVAL;
  518                         /* illegal entry, stop */
  519                         break;
  520                 }
  521 
  522                 if (isonum_711(ep->flags)&2)
  523                         idp->current.d_fileno = isodirino(ep, imp);
  524                 else
  525                         idp->current.d_fileno = dbtob(bp->b_blkno) +
  526                                 entryoffsetinblock;
  527 
  528                 idp->curroff += reclen;
  529 
  530                 switch (imp->iso_ftype) {
  531                 case ISO_FTYPE_RRIP:
  532                         cd9660_rrip_getname(ep, idp->current.d_name, &namelen,
  533                             &idp->current.d_fileno, imp);
  534                         idp->current.d_namlen = (u_char)namelen;
  535                         if (idp->current.d_namlen)
  536                                 error = iso_uiodir(idp, &idp->current,
  537                                     idp->curroff);
  538                         break;
  539                 default:        /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
  540                         isofntrans(ep->name, idp->current.d_namlen,
  541                                    idp->current.d_name, &namelen,
  542                                    imp->iso_ftype == ISO_FTYPE_9660,
  543                                    (imp->im_flags & ISOFSMNT_NOCASETRANS) == 0,
  544                                    isonum_711(ep->flags)&4,
  545                                    imp->im_joliet_level);
  546                         switch (idp->current.d_name[0]) {
  547                         case 0:
  548                                 idp->current.d_name[0] = '.';
  549                                 idp->current.d_namlen = 1;
  550                                 error = iso_uiodir(idp, &idp->current,
  551                                     idp->curroff);
  552                                 break;
  553                         case 1:
  554                                 strlcpy(idp->current.d_name, "..",
  555                                     sizeof(idp->current.d_name));
  556                                 idp->current.d_namlen = 2;
  557                                 error = iso_uiodir(idp, &idp->current,
  558                                     idp->curroff);
  559                                 break;
  560                         default:
  561                                 idp->current.d_namlen = (u_char)namelen;
  562                                 if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
  563                                         error = iso_shipdir(idp);
  564                                 else
  565                                         error = iso_uiodir(idp, &idp->current,
  566                                             idp->curroff);
  567                                 break;
  568                         }
  569                 }
  570                 if (error)
  571                         break;
  572 
  573                 entryoffsetinblock += reclen;
  574         }
  575 
  576         if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
  577                 idp->current.d_namlen = 0;
  578                 error = iso_shipdir(idp);
  579         }
  580         if (error < 0)
  581                 error = 0;
  582 
  583         if (ap->a_ncookies != NULL) {
  584                 if (error)
  585                         free(cookies, M_TEMP);
  586                 else {
  587                         /*
  588                          * Work out the number of cookies actually used.
  589                          */
  590                         *ap->a_ncookies = ncookies - idp->ncookies;
  591                         *ap->a_cookies = cookies;
  592                 }
  593         }
  594 
  595         if (bp)
  596                 brelse (bp);
  597 
  598         uio->uio_offset = idp->uio_off;
  599         *ap->a_eofflag = idp->eofflag;
  600 
  601         FREE(idp, M_TEMP);
  602 
  603         return (error);
  604 }
  605 
  606 /*
  607  * Return target name of a symbolic link
  608  * Shouldn't we get the parent vnode and read the data from there?
  609  * This could eventually result in deadlocks in cd9660_lookup.
  610  * But otherwise the block read here is in the block buffer two times.
  611  */
  612 typedef struct iso_directory_record ISODIR;
  613 typedef struct iso_node             ISONODE;
  614 typedef struct iso_mnt              ISOMNT;
  615 int
  616 cd9660_readlink(v)
  617         void *v;
  618 {
  619         struct vop_readlink_args /* {
  620                 struct vnode *a_vp;
  621                 struct uio *a_uio;
  622                 struct ucred *a_cred;
  623         } */ *ap = v;
  624         ISONODE *ip;
  625         ISODIR  *dirp;
  626         ISOMNT  *imp;
  627         struct  buf *bp;
  628         struct  uio *uio;
  629         u_short symlen;
  630         int     error;
  631         char    *symname;
  632 
  633         ip  = VTOI(ap->a_vp);
  634         imp = ip->i_mnt;
  635         uio = ap->a_uio;
  636 
  637         if (imp->iso_ftype != ISO_FTYPE_RRIP)
  638                 return (EINVAL);
  639 
  640         /*
  641          * Get parents directory record block that this inode included.
  642          */
  643         error = bread(imp->im_devvp,
  644                       (ip->i_number >> imp->im_bshift) <<
  645                       (imp->im_bshift - DEV_BSHIFT),
  646                       imp->logical_block_size, NOCRED, &bp);
  647         if (error) {
  648                 brelse(bp);
  649                 return (EINVAL);
  650         }
  651 
  652         /*
  653          * Setup the directory pointer for this inode
  654          */
  655         dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
  656 
  657         /*
  658          * Just make sure, we have a right one....
  659          *   1: Check not cross boundary on block
  660          */
  661         if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
  662             > imp->logical_block_size) {
  663                 brelse(bp);
  664                 return (EINVAL);
  665         }
  666 
  667         /*
  668          * Now get a buffer
  669          * Abuse a namei buffer for now.
  670          */
  671         if (uio->uio_segflg == UIO_SYSSPACE &&
  672             uio->uio_iov->iov_len >= MAXPATHLEN)
  673                 symname = uio->uio_iov->iov_base;
  674         else
  675                 MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
  676         
  677         /*
  678          * Ok, we just gathering a symbolic name in SL record.
  679          */
  680         if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
  681                 if (uio->uio_segflg != UIO_SYSSPACE ||
  682                     uio->uio_iov->iov_len < MAXPATHLEN)
  683                         FREE(symname, M_NAMEI);
  684                 brelse(bp);
  685                 return (EINVAL);
  686         }
  687         /*
  688          * Don't forget before you leave from home ;-)
  689          */
  690         brelse(bp);
  691 
  692         /*
  693          * return with the symbolic name to caller's.
  694          */
  695         if (uio->uio_segflg != UIO_SYSSPACE ||
  696             uio->uio_iov->iov_len < MAXPATHLEN) {
  697                 error = uiomove(symname, symlen, uio);
  698                 FREE(symname, M_NAMEI);
  699                 return (error);
  700         }
  701         uio->uio_resid -= symlen;
  702         uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen;
  703         uio->uio_iov->iov_len -= symlen;
  704         return (0);
  705 }
  706 
  707 int
  708 cd9660_link(v)
  709         void *v;
  710 {
  711         struct vop_link_args /* {
  712                 struct vnode *a_dvp;
  713                 struct vnode *a_vp;
  714                 struct componentname *a_cnp;
  715         } */ *ap = v;
  716 
  717         VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  718         vput(ap->a_dvp);
  719         return (EROFS);
  720 }
  721 
  722 int
  723 cd9660_symlink(v)
  724         void *v;
  725 {
  726         struct vop_symlink_args /* {
  727                 struct vnode *a_dvp;
  728                 struct vnode **a_vpp;
  729                 struct componentname *a_cnp;
  730                 struct vattr *a_vap;
  731                 char *a_target;
  732         } */ *ap = v;
  733 
  734         VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  735         vput(ap->a_dvp);
  736         return (EROFS);
  737 }
  738 
  739 /*
  740  * Calculate the logical to physical mapping if not done already,
  741  * then call the device strategy routine.
  742  */
  743 int
  744 cd9660_strategy(v)
  745         void *v;
  746 {
  747         struct vop_strategy_args /* {
  748                 struct vnode *a_vp;
  749                 struct buf *a_bp;
  750         } */ *ap = v;
  751         struct buf *bp = ap->a_bp;
  752         struct vnode *vp = ap->a_vp;
  753         struct iso_node *ip;
  754         int error;
  755 
  756         ip = VTOI(vp);
  757         if (vp->v_type == VBLK || vp->v_type == VCHR)
  758                 panic("cd9660_strategy: spec");
  759         if (bp->b_blkno == bp->b_lblkno) {
  760                 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
  761                 if (error) {
  762                         bp->b_error = error;
  763                         bp->b_flags |= B_ERROR;
  764                         biodone(bp);
  765                         return (error);
  766                 }
  767                 if ((long)bp->b_blkno == -1)
  768                         clrbuf(bp);
  769         }
  770         if ((long)bp->b_blkno == -1) {
  771                 biodone(bp);
  772                 return (0);
  773         }
  774         vp = ip->i_devvp;
  775         return (VOP_STRATEGY(vp, bp));
  776 }
  777 
  778 /*
  779  * Print out the contents of an inode.
  780  */
  781 /*ARGSUSED*/
  782 int
  783 cd9660_print(v)
  784         void *v;
  785 {
  786 
  787         printf("tag VT_ISOFS, isofs vnode\n");
  788         return (0);
  789 }
  790 
  791 /*
  792  * Return POSIX pathconf information applicable to cd9660 filesystems.
  793  */
  794 int
  795 cd9660_pathconf(v)
  796         void *v;
  797 {
  798         struct vop_pathconf_args /* {
  799                 struct vnode *a_vp;
  800                 int a_name;
  801                 register_t *a_retval;
  802         } */ *ap = v;
  803         switch (ap->a_name) {
  804         case _PC_LINK_MAX:
  805                 *ap->a_retval = 1;
  806                 return (0);
  807         case _PC_NAME_MAX:
  808                 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
  809                         *ap->a_retval = NAME_MAX;
  810                 else
  811                         *ap->a_retval = 37;
  812                 return (0);
  813         case _PC_PATH_MAX:
  814                 *ap->a_retval = PATH_MAX;
  815                 return (0);
  816         case _PC_PIPE_BUF:
  817                 *ap->a_retval = PIPE_BUF;
  818                 return (0);
  819         case _PC_CHOWN_RESTRICTED:
  820                 *ap->a_retval = 1;
  821                 return (0);
  822         case _PC_NO_TRUNC:
  823                 *ap->a_retval = 1;
  824                 return (0);
  825         case _PC_SYNC_IO:
  826                 *ap->a_retval = 1;
  827                 return (0);
  828         case _PC_FILESIZEBITS:
  829                 *ap->a_retval = 32;
  830                 return (0);
  831         default:
  832                 return (EINVAL);
  833         }
  834         /* NOTREACHED */
  835 }
  836 
  837 /*
  838  * Allow changing the size for special files (and fifos).
  839  */
  840 int
  841 cd9660_setattr(v)
  842         void *v;
  843 {
  844         struct vop_setattr_args /* {
  845                 struct vnodeop_desc *a_desc;
  846                 struct vnode *a_vp;
  847                 struct vattr *a_vap;
  848                 struct ucred *a_cred;
  849                 struct proc *a_p;
  850         } */ *ap = v;
  851         struct vattr *vap = ap->a_vap;
  852         struct vnode *vp = ap->a_vp;
  853         
  854         /*
  855          * Only size is changeable.
  856          */
  857         if (vap->va_type != VNON
  858             || vap->va_nlink != (nlink_t)VNOVAL
  859             || vap->va_fsid != VNOVAL
  860             || vap->va_fileid != VNOVAL
  861             || vap->va_blocksize != VNOVAL
  862             || vap->va_rdev != (dev_t)VNOVAL
  863             || (int)vap->va_bytes != VNOVAL
  864             || vap->va_gen != VNOVAL
  865             || vap->va_flags != VNOVAL
  866             || vap->va_uid != (uid_t)VNOVAL
  867             || vap->va_gid != (gid_t)VNOVAL
  868             || vap->va_atime.tv_sec != VNOVAL
  869             || vap->va_mtime.tv_sec != VNOVAL
  870             || vap->va_mode != (mode_t)VNOVAL)
  871                 return EOPNOTSUPP;
  872         
  873         if (vap->va_size != VNOVAL
  874             && vp->v_type != VCHR
  875             && vp->v_type != VBLK
  876             && vp->v_type != VFIFO
  877             )
  878                 return EOPNOTSUPP;
  879         
  880         return VOP_TRUNCATE(vp, vap->va_size, 0, ap->a_cred, ap->a_p);
  881 }
  882 
  883 /*
  884  * Global vfs data structures for isofs
  885  */
  886 #define cd9660_create   genfs_eopnotsupp
  887 #define cd9660_mknod    genfs_eopnotsupp
  888 #define cd9660_write    genfs_eopnotsupp
  889 #define cd9660_lease_check      genfs_lease_check
  890 #define cd9660_fsync    genfs_nullop
  891 #define cd9660_remove   genfs_eopnotsupp
  892 #define cd9660_rename   genfs_eopnotsupp
  893 #define cd9660_mkdir    genfs_eopnotsupp
  894 #define cd9660_rmdir    genfs_eopnotsupp
  895 #define cd9660_advlock  genfs_einval
  896 #define cd9660_valloc   genfs_eopnotsupp
  897 #define cd9660_vfree    genfs_nullop
  898 #define cd9660_truncate genfs_eopnotsupp
  899 #define cd9660_update   genfs_nullop
  900 #define cd9660_bwrite   genfs_eopnotsupp
  901 #define cd9660_revoke   genfs_revoke
  902 
  903 /*
  904  * Global vfs data structures for cd9660
  905  */
  906 int (**cd9660_vnodeop_p) __P((void *));
  907 const struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
  908         { &vop_default_desc, vn_default_error },
  909         { &vop_lookup_desc, cd9660_lookup },            /* lookup */
  910         { &vop_create_desc, cd9660_create },            /* create */
  911         { &vop_mknod_desc, cd9660_mknod },              /* mknod */
  912         { &vop_open_desc, cd9660_open },                /* open */
  913         { &vop_close_desc, cd9660_close },              /* close */
  914         { &vop_access_desc, cd9660_access },            /* access */
  915         { &vop_getattr_desc, cd9660_getattr },          /* getattr */
  916         { &vop_setattr_desc, cd9660_setattr },          /* setattr */
  917         { &vop_read_desc, cd9660_read },                /* read */
  918         { &vop_write_desc, cd9660_write },              /* write */
  919         { &vop_lease_desc, cd9660_lease_check },        /* lease */
  920         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  921         { &vop_ioctl_desc, cd9660_ioctl },              /* ioctl */
  922         { &vop_poll_desc, cd9660_poll },                /* poll */
  923         { &vop_revoke_desc, cd9660_revoke },            /* revoke */
  924         { &vop_mmap_desc, cd9660_mmap },                /* mmap */
  925         { &vop_fsync_desc, cd9660_fsync },              /* fsync */
  926         { &vop_seek_desc, cd9660_seek },                /* seek */
  927         { &vop_remove_desc, cd9660_remove },            /* remove */
  928         { &vop_link_desc, cd9660_link },                /* link */
  929         { &vop_rename_desc, cd9660_rename },            /* rename */
  930         { &vop_mkdir_desc, cd9660_mkdir },              /* mkdir */
  931         { &vop_rmdir_desc, cd9660_rmdir },              /* rmdir */
  932         { &vop_symlink_desc, cd9660_symlink },          /* symlink */
  933         { &vop_readdir_desc, cd9660_readdir },          /* readdir */
  934         { &vop_readlink_desc, cd9660_readlink },        /* readlink */
  935         { &vop_abortop_desc, cd9660_abortop },          /* abortop */
  936         { &vop_inactive_desc, cd9660_inactive },        /* inactive */
  937         { &vop_reclaim_desc, cd9660_reclaim },          /* reclaim */
  938         { &vop_lock_desc, genfs_lock },                 /* lock */
  939         { &vop_unlock_desc, genfs_unlock },             /* unlock */
  940         { &vop_bmap_desc, cd9660_bmap },                /* bmap */
  941         { &vop_strategy_desc, cd9660_strategy },        /* strategy */
  942         { &vop_print_desc, cd9660_print },              /* print */
  943         { &vop_islocked_desc, genfs_islocked },         /* islocked */
  944         { &vop_pathconf_desc, cd9660_pathconf },        /* pathconf */
  945         { &vop_advlock_desc, cd9660_advlock },          /* advlock */
  946         { &vop_blkatoff_desc, cd9660_blkatoff },        /* blkatoff */
  947         { &vop_valloc_desc, cd9660_valloc },            /* valloc */
  948         { &vop_vfree_desc, cd9660_vfree },              /* vfree */
  949         { &vop_truncate_desc, cd9660_truncate },        /* truncate */
  950         { &vop_update_desc, cd9660_update },            /* update */
  951         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
  952         { &vop_getpages_desc, genfs_getpages },         /* getpages */
  953         { &vop_putpages_desc, genfs_putpages },         /* putpages */
  954         { NULL, NULL }
  955 };
  956 const struct vnodeopv_desc cd9660_vnodeop_opv_desc =
  957         { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
  958 
  959 /*
  960  * Special device vnode ops
  961  */
  962 int (**cd9660_specop_p) __P((void *));
  963 const struct vnodeopv_entry_desc cd9660_specop_entries[] = {
  964         { &vop_default_desc, vn_default_error },
  965         { &vop_lookup_desc, spec_lookup },              /* lookup */
  966         { &vop_create_desc, spec_create },              /* create */
  967         { &vop_mknod_desc, spec_mknod },                /* mknod */
  968         { &vop_open_desc, spec_open },                  /* open */
  969         { &vop_close_desc, spec_close },                /* close */
  970         { &vop_access_desc, cd9660_access },            /* access */
  971         { &vop_getattr_desc, cd9660_getattr },          /* getattr */
  972         { &vop_setattr_desc, cd9660_setattr },          /* setattr */
  973         { &vop_read_desc, spec_read },                  /* read */
  974         { &vop_write_desc, spec_write },                /* write */
  975         { &vop_lease_desc, spec_lease_check },          /* lease */
  976         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  977         { &vop_ioctl_desc, spec_ioctl },                /* ioctl */
  978         { &vop_poll_desc, spec_poll },                  /* poll */
  979         { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
  980         { &vop_revoke_desc, spec_revoke },              /* revoke */
  981         { &vop_mmap_desc, spec_mmap },                  /* mmap */
  982         { &vop_fsync_desc, spec_fsync },                /* fsync */
  983         { &vop_seek_desc, spec_seek },                  /* seek */
  984         { &vop_remove_desc, spec_remove },              /* remove */
  985         { &vop_link_desc, spec_link },                  /* link */
  986         { &vop_rename_desc, spec_rename },              /* rename */
  987         { &vop_mkdir_desc, spec_mkdir },                /* mkdir */
  988         { &vop_rmdir_desc, spec_rmdir },                /* rmdir */
  989         { &vop_symlink_desc, spec_symlink },            /* symlink */
  990         { &vop_readdir_desc, spec_readdir },            /* readdir */
  991         { &vop_readlink_desc, spec_readlink },          /* readlink */
  992         { &vop_abortop_desc, spec_abortop },            /* abortop */
  993         { &vop_inactive_desc, cd9660_inactive },        /* inactive */
  994         { &vop_reclaim_desc, cd9660_reclaim },          /* reclaim */
  995         { &vop_lock_desc, genfs_lock },                 /* lock */
  996         { &vop_unlock_desc, genfs_unlock },             /* unlock */
  997         { &vop_bmap_desc, spec_bmap },                  /* bmap */
  998         { &vop_strategy_desc, spec_strategy },          /* strategy */
  999         { &vop_print_desc, cd9660_print },              /* print */
 1000         { &vop_islocked_desc, genfs_islocked },         /* islocked */
 1001         { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
 1002         { &vop_advlock_desc, spec_advlock },            /* advlock */
 1003         { &vop_blkatoff_desc, spec_blkatoff },          /* blkatoff */
 1004         { &vop_valloc_desc, spec_valloc },              /* valloc */
 1005         { &vop_vfree_desc, spec_vfree },                /* vfree */
 1006         { &vop_truncate_desc, spec_truncate },          /* truncate */
 1007         { &vop_update_desc, cd9660_update },            /* update */
 1008         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
 1009         { &vop_getpages_desc, spec_getpages },          /* getpages */
 1010         { &vop_putpages_desc, spec_putpages },          /* putpages */
 1011         { NULL, NULL }
 1012 };
 1013 const struct vnodeopv_desc cd9660_specop_opv_desc =
 1014         { &cd9660_specop_p, cd9660_specop_entries };
 1015 
 1016 int (**cd9660_fifoop_p) __P((void *));
 1017 const struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
 1018         { &vop_default_desc, vn_default_error },
 1019         { &vop_lookup_desc, fifo_lookup },              /* lookup */
 1020         { &vop_create_desc, fifo_create },              /* create */
 1021         { &vop_mknod_desc, fifo_mknod },                /* mknod */
 1022         { &vop_open_desc, fifo_open },                  /* open */
 1023         { &vop_close_desc, fifo_close },                /* close */
 1024         { &vop_access_desc, cd9660_access },            /* access */
 1025         { &vop_getattr_desc, cd9660_getattr },          /* getattr */
 1026         { &vop_setattr_desc, cd9660_setattr },          /* setattr */
 1027         { &vop_read_desc, fifo_read },                  /* read */
 1028         { &vop_write_desc, fifo_write },                /* write */
 1029         { &vop_lease_desc, fifo_lease_check },          /* lease */
 1030         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
 1031         { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
 1032         { &vop_poll_desc, fifo_poll },                  /* poll */
 1033         { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
 1034         { &vop_revoke_desc, fifo_revoke },              /* revoke */
 1035         { &vop_mmap_desc, fifo_mmap },                  /* mmap */
 1036         { &vop_fsync_desc, fifo_fsync },                /* fsync */
 1037         { &vop_seek_desc, fifo_seek },                  /* seek */
 1038         { &vop_remove_desc, fifo_remove },              /* remove */
 1039         { &vop_link_desc, fifo_link }   ,               /* link */
 1040         { &vop_rename_desc, fifo_rename },              /* rename */
 1041         { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
 1042         { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
 1043         { &vop_symlink_desc, fifo_symlink },            /* symlink */
 1044         { &vop_readdir_desc, fifo_readdir },            /* readdir */
 1045         { &vop_readlink_desc, fifo_readlink },          /* readlink */
 1046         { &vop_abortop_desc, fifo_abortop },            /* abortop */
 1047         { &vop_inactive_desc, cd9660_inactive },        /* inactive */
 1048         { &vop_reclaim_desc, cd9660_reclaim },          /* reclaim */
 1049         { &vop_lock_desc, genfs_lock },                 /* lock */
 1050         { &vop_unlock_desc, genfs_unlock },             /* unlock */
 1051         { &vop_bmap_desc, fifo_bmap },                  /* bmap */
 1052         { &vop_strategy_desc, fifo_strategy },          /* strategy */
 1053         { &vop_print_desc, cd9660_print },              /* print */
 1054         { &vop_islocked_desc, genfs_islocked },         /* islocked */
 1055         { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
 1056         { &vop_advlock_desc, fifo_advlock },            /* advlock */
 1057         { &vop_blkatoff_desc, fifo_blkatoff },          /* blkatoff */
 1058         { &vop_valloc_desc, fifo_valloc },              /* valloc */
 1059         { &vop_vfree_desc, fifo_vfree },                /* vfree */
 1060         { &vop_truncate_desc, fifo_truncate },          /* truncate */
 1061         { &vop_update_desc, cd9660_update },            /* update */
 1062         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
 1063         { &vop_putpages_desc, fifo_putpages },          /* putpages */
 1064         { NULL, NULL }
 1065 };
 1066 const struct vnodeopv_desc cd9660_fifoop_opv_desc =
 1067         { &cd9660_fifoop_p, cd9660_fifoop_entries };

Cache object: db19a635e6ff47aaa2b7fe2ac732e8c1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.