[BACK]Return to cd9660_vnops.c CVS log [TXT][DIR] Up to [local] / sys / isofs / cd9660

Annotation of sys/isofs/cd9660/cd9660_vnops.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: cd9660_vnops.c,v 1.43 2007/06/06 17:15:13 deraadt 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/proc.h>
                     49: #include <sys/conf.h>
                     50: #include <sys/mount.h>
                     51: #include <sys/vnode.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/cdio.h>
                     58: #include <sys/poll.h>
                     59:
                     60: #include <miscfs/fifofs/fifo.h>
                     61: #include <miscfs/specfs/specdev.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: /*
                     69:  * Structure for reading directories
                     70:  */
                     71: struct isoreaddir {
                     72:        struct dirent saveent;
                     73:        struct dirent assocent;
                     74:        struct dirent current;
                     75:        off_t saveoff;
                     76:        off_t assocoff;
                     77:        off_t curroff;
                     78:        struct uio *uio;
                     79:        off_t uio_off;
                     80:        int eofflag;
                     81:        u_long *cookies;
                     82:        int ncookies;
                     83: };
                     84:
                     85: int    iso_uiodir(struct isoreaddir *, struct dirent *, off_t);
                     86: int    iso_shipdir(struct isoreaddir *);
                     87:
                     88: #if 0
                     89: /*
                     90:  * Mknod vnode call
                     91:  *  Actually remap the device number
                     92:  */
                     93: int
                     94: cd9660_mknod(ndp, vap, cred, p)
                     95:        struct nameidata *ndp;
                     96:        struct ucred *cred;
                     97:        struct vattr *vap;
                     98:        struct proc *p;
                     99: {
                    100: #ifndef        ISODEVMAP
                    101:        pool_put(&namei_pool, ndp->ni_pnbuf);
                    102:        vput(ndp->ni_dvp);
                    103:        vput(ndp->ni_vp);
                    104:        return (EINVAL);
                    105: #else
                    106:        register struct vnode *vp;
                    107:        struct iso_node *ip;
                    108:        struct iso_dnode *dp;
                    109:        int error;
                    110:
                    111:        vp = ndp->ni_vp;
                    112:        ip = VTOI(vp);
                    113:
                    114:        if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
                    115:            || vap->va_type != vp->v_type
                    116:            || (vap->va_type != VCHR && vap->va_type != VBLK)) {
                    117:                pool_put(&namei_pool, ndp->ni_pnbuf);
                    118:                vput(ndp->ni_dvp);
                    119:                vput(ndp->ni_vp);
                    120:                return (EINVAL);
                    121:        }
                    122:
                    123:        dp = iso_dmap(ip->i_dev,ip->i_number,1);
                    124:        if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
                    125:                /* same as the unmapped one, delete the mapping */
                    126:                remque(dp);
                    127:                FREE(dp, M_CACHE);
                    128:        } else
                    129:                /* enter new mapping */
                    130:                dp->d_dev = vap->va_rdev;
                    131:
                    132:        /*
                    133:         * Remove inode so that it will be reloaded by iget and
                    134:         * checked to see if it is an alias of an existing entry
                    135:         * in the inode cache.
                    136:         */
                    137:        vput(vp);
                    138:        vp->v_type = VNON;
                    139:        vgone(vp);
                    140:        return (0);
                    141: #endif
                    142: }
                    143: #endif
                    144:
                    145: /*
                    146:  * Setattr call. Only allowed for block and character special devices.
                    147:  */
                    148: int
                    149: cd9660_setattr(v)
                    150:        void *v;
                    151: {
                    152:        struct vop_setattr_args *ap = v;
                    153:        struct vnode *vp = ap->a_vp;
                    154:        struct vattr *vap = ap->a_vap;
                    155:
                    156:        if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
                    157:            vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
                    158:            vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
                    159:                return (EROFS);
                    160:        if (vap->va_size != VNOVAL) {
                    161:                switch (vp->v_type) {
                    162:                case VDIR:
                    163:                        return (EISDIR);
                    164:                case VLNK:
                    165:                case VREG:
                    166:                        return (EROFS);
                    167:                case VCHR:
                    168:                case VBLK:
                    169:                case VSOCK:
                    170:                case VFIFO:
                    171:                        return (0);
                    172:                default:
                    173:                        return (EINVAL);
                    174:                }
                    175:        }
                    176:
                    177:        return (EINVAL);
                    178: }
                    179:
                    180: /*
                    181:  * Open called.
                    182:  *
                    183:  * Nothing to do.
                    184:  */
                    185: /* ARGSUSED */
                    186: int
                    187: cd9660_open(v)
                    188:        void *v;
                    189: {
                    190:        return (0);
                    191: }
                    192:
                    193: /*
                    194:  * Close called
                    195:  *
                    196:  * Update the times on the inode on writeable file systems.
                    197:  */
                    198: /* ARGSUSED */
                    199: int
                    200: cd9660_close(v)
                    201:        void *v;
                    202: {
                    203:        return (0);
                    204: }
                    205:
                    206: /*
                    207:  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
                    208:  * The mode is shifted to select the owner/group/other fields. The
                    209:  * super user is granted all permissions.
                    210:  */
                    211: int
                    212: cd9660_access(v)
                    213:        void *v;
                    214: {
                    215:        struct vop_access_args *ap = v;
                    216:        struct iso_node *ip = VTOI(ap->a_vp);
                    217:
                    218:        return (vaccess(ip->inode.iso_mode & ALLPERMS, ip->inode.iso_uid,
                    219:            ip->inode.iso_gid, ap->a_mode, ap->a_cred));
                    220: }
                    221:
                    222: int
                    223: cd9660_getattr(v)
                    224:        void *v;
                    225: {
                    226:        struct vop_getattr_args *ap = v;
                    227:        struct vnode *vp = ap->a_vp;
                    228:        register struct vattr *vap = ap->a_vap;
                    229:        register struct iso_node *ip = VTOI(vp);
                    230:
                    231:        vap->va_fsid    = ip->i_dev;
                    232:        vap->va_fileid  = ip->i_number;
                    233:
                    234:        vap->va_mode    = ip->inode.iso_mode & ALLPERMS;
                    235:        vap->va_nlink   = ip->inode.iso_links;
                    236:        vap->va_uid     = ip->inode.iso_uid;
                    237:        vap->va_gid     = ip->inode.iso_gid;
                    238:        vap->va_atime   = ip->inode.iso_atime;
                    239:        vap->va_mtime   = ip->inode.iso_mtime;
                    240:        vap->va_ctime   = ip->inode.iso_ctime;
                    241:        vap->va_rdev    = ip->inode.iso_rdev;
                    242:
                    243:        vap->va_size    = (u_quad_t) ip->i_size;
                    244:        if (ip->i_size == 0 && vp->v_type  == VLNK) {
                    245:                struct vop_readlink_args rdlnk;
                    246:                struct iovec aiov;
                    247:                struct uio auio;
                    248:                char *cp;
                    249:
                    250:                MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
                    251:                aiov.iov_base = cp;
                    252:                aiov.iov_len = MAXPATHLEN;
                    253:                auio.uio_iov = &aiov;
                    254:                auio.uio_iovcnt = 1;
                    255:                auio.uio_offset = 0;
                    256:                auio.uio_rw = UIO_READ;
                    257:                auio.uio_segflg = UIO_SYSSPACE;
                    258:                auio.uio_procp = ap->a_p;
                    259:                auio.uio_resid = MAXPATHLEN;
                    260:                rdlnk.a_uio = &auio;
                    261:                rdlnk.a_vp = ap->a_vp;
                    262:                rdlnk.a_cred = ap->a_cred;
                    263:                if (cd9660_readlink(&rdlnk) == 0)
                    264:                        vap->va_size = MAXPATHLEN - auio.uio_resid;
                    265:                FREE(cp, M_TEMP);
                    266:        }
                    267:        vap->va_flags   = 0;
                    268:        vap->va_gen = 1;
                    269:        vap->va_blocksize = ip->i_mnt->logical_block_size;
                    270:        vap->va_bytes   = (u_quad_t) ip->i_size;
                    271:        vap->va_type    = vp->v_type;
                    272:        return (0);
                    273: }
                    274:
                    275: /*
                    276:  * Vnode op for reading.
                    277:  */
                    278: int
                    279: cd9660_read(v)
                    280:        void *v;
                    281: {
                    282:        struct vop_read_args *ap = v;
                    283:        struct vnode *vp = ap->a_vp;
                    284:        register struct uio *uio = ap->a_uio;
                    285:        register struct iso_node *ip = VTOI(vp);
                    286:        register struct iso_mnt *imp;
                    287:        struct buf *bp;
                    288:        daddr64_t lbn, rablock;
                    289:        off_t diff;
                    290:        int error = 0;
                    291:        long size, n, on;
                    292:
                    293:        if (uio->uio_resid == 0)
                    294:                return (0);
                    295:        if (uio->uio_offset < 0)
                    296:                return (EINVAL);
                    297:        ip->i_flag |= IN_ACCESS;
                    298:        imp = ip->i_mnt;
                    299:        do {
                    300:                struct cluster_info *ci = &ip->i_ci;
                    301:
                    302:                lbn = lblkno(imp, uio->uio_offset);
                    303:                on = blkoff(imp, uio->uio_offset);
                    304:                n = min((u_int)(imp->logical_block_size - on),
                    305:                        uio->uio_resid);
                    306:                diff = (off_t)ip->i_size - uio->uio_offset;
                    307:                if (diff <= 0)
                    308:                        return (0);
                    309:                if (diff < n)
                    310:                        n = diff;
                    311:                size = blksize(imp, ip, lbn);
                    312:                rablock = lbn + 1;
                    313: #define MAX_RA 32
                    314:                if (ci->ci_lastr + 1 == lbn) {
                    315:                        struct ra {
                    316:                                daddr64_t blks[MAX_RA];
                    317:                                int sizes[MAX_RA];
                    318:                        } *ra;
                    319:                        int i;
                    320:
                    321:                        MALLOC(ra, struct ra *, sizeof *ra,
                    322:                            M_TEMP, M_WAITOK);
                    323:                        for (i = 0; i < MAX_RA &&
                    324:                            lblktosize(imp, (rablock + i)) < ip->i_size;
                    325:                            i++) {
                    326:                                ra->blks[i] = rablock + i;
                    327:                                ra->sizes[i] = blksize(imp, ip, rablock + i);
                    328:                        }
                    329:                        error = breadn(vp, lbn, size, ra->blks,
                    330:                            ra->sizes, i, NOCRED, &bp);
                    331:                        FREE(ra, M_TEMP);
                    332:                } else
                    333:                        error = bread(vp, lbn, size, NOCRED, &bp);
                    334:                ci->ci_lastr = lbn;
                    335:                n = min(n, size - bp->b_resid);
                    336:                if (error) {
                    337:                        brelse(bp);
                    338:                        return (error);
                    339:                }
                    340:
                    341:                error = uiomove(bp->b_data + on, (int)n, uio);
                    342:
                    343:                 if (n + on == imp->logical_block_size ||
                    344:                    uio->uio_offset == (off_t)ip->i_size)
                    345:                        bp->b_flags |= B_AGE;
                    346:                brelse(bp);
                    347:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    348:        return (error);
                    349: }
                    350:
                    351: /* ARGSUSED */
                    352: int
                    353: cd9660_ioctl(v)
                    354:        void *v;
                    355: {
                    356:        return (ENOTTY);
                    357: }
                    358:
                    359: /* ARGSUSED */
                    360: int
                    361: cd9660_poll(v)
                    362:        void *v;
                    363: {
                    364:        struct vop_poll_args *ap = v;
                    365:
                    366:        /*
                    367:         * We should really check to see if I/O is possible.
                    368:         */
                    369:        return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
                    370: }
                    371:
                    372: /*
                    373:  * Mmap a file
                    374:  *
                    375:  * NB Currently unsupported.
                    376:  */
                    377: /* ARGSUSED */
                    378: int
                    379: cd9660_mmap(v)
                    380:        void *v;
                    381: {
                    382:
                    383:        return (EINVAL);
                    384: }
                    385:
                    386: /*
                    387:  * Seek on a file
                    388:  *
                    389:  * Nothing to do, so just return.
                    390:  */
                    391: /* ARGSUSED */
                    392: int
                    393: cd9660_seek(v)
                    394:        void *v;
                    395: {
                    396:        return (0);
                    397: }
                    398:
                    399: int
                    400: iso_uiodir(idp,dp,off)
                    401:        struct isoreaddir *idp;
                    402:        struct dirent *dp;
                    403:        off_t off;
                    404: {
                    405:        int error;
                    406:
                    407:        dp->d_name[dp->d_namlen] = 0;
                    408:        dp->d_reclen = DIRENT_SIZE(dp);
                    409:
                    410:        if (idp->uio->uio_resid < dp->d_reclen) {
                    411:                idp->eofflag = 0;
                    412:                return (-1);
                    413:        }
                    414:
                    415:        if (idp->cookies) {
                    416:                if (idp->ncookies <= 0) {
                    417:                        idp->eofflag = 0;
                    418:                        return (-1);
                    419:                }
                    420:
                    421:                *idp->cookies++ = off;
                    422:                --idp->ncookies;
                    423:        }
                    424:
                    425:        if ((error = uiomove((caddr_t)dp, dp->d_reclen, idp->uio)) != 0)
                    426:                return (error);
                    427:        idp->uio_off = off;
                    428:        return (0);
                    429: }
                    430:
                    431: int
                    432: iso_shipdir(idp)
                    433:        struct isoreaddir *idp;
                    434: {
                    435:        struct dirent *dp;
                    436:        int cl, sl, assoc;
                    437:        int error;
                    438:        char *cname, *sname;
                    439:
                    440:        cl = idp->current.d_namlen;
                    441:        cname = idp->current.d_name;
                    442:
                    443:        if ((assoc = cl > 1 && *cname == ASSOCCHAR)) {
                    444:                cl--;
                    445:                cname++;
                    446:        }
                    447:
                    448:        dp = &idp->saveent;
                    449:        sname = dp->d_name;
                    450:        if (!(sl = dp->d_namlen)) {
                    451:                dp = &idp->assocent;
                    452:                sname = dp->d_name + 1;
                    453:                sl = dp->d_namlen - 1;
                    454:        }
                    455:        if (sl > 0) {
                    456:                if (sl != cl
                    457:                    || bcmp(sname,cname,sl)) {
                    458:                        if (idp->assocent.d_namlen) {
                    459:                                error = iso_uiodir(idp, &idp->assocent,
                    460:                                                   idp->assocoff);
                    461:                                if (error)
                    462:                                        return (error);
                    463:                                idp->assocent.d_namlen = 0;
                    464:                        }
                    465:                        if (idp->saveent.d_namlen) {
                    466:                                error = iso_uiodir(idp, &idp->saveent,
                    467:                                                   idp->saveoff);
                    468:                                if (error)
                    469:                                        return (error);
                    470:                                idp->saveent.d_namlen = 0;
                    471:                        }
                    472:                }
                    473:        }
                    474:        idp->current.d_reclen = DIRENT_SIZE(&idp->current);
                    475:        if (assoc) {
                    476:                idp->assocoff = idp->curroff;
                    477:                bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
                    478:        } else {
                    479:                idp->saveoff = idp->curroff;
                    480:                bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
                    481:        }
                    482:        return (0);
                    483: }
                    484:
                    485: /*
                    486:  * Vnode op for readdir
                    487:  */
                    488: int
                    489: cd9660_readdir(v)
                    490:        void *v;
                    491: {
                    492:        struct vop_readdir_args *ap = v;
                    493:        register struct uio *uio = ap->a_uio;
                    494:        struct isoreaddir *idp;
                    495:        struct vnode *vdp = ap->a_vp;
                    496:        struct iso_node *dp;
                    497:        struct iso_mnt *imp;
                    498:        struct buf *bp = NULL;
                    499:        struct iso_directory_record *ep;
                    500:        int entryoffsetinblock;
                    501:        doff_t endsearch;
                    502:        u_long bmask;
                    503:        int error = 0;
                    504:        int reclen;
                    505:        u_short namelen;
                    506:        int  ncookies = 0;
                    507:        u_long *cookies = NULL;
                    508:
                    509:        dp = VTOI(vdp);
                    510:        imp = dp->i_mnt;
                    511:        bmask = imp->im_bmask;
                    512:
                    513:        MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
                    514:        idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
                    515:        /*
                    516:         * XXX
                    517:         * Is it worth trying to figure out the type?
                    518:         */
                    519:        idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
                    520:            DT_UNKNOWN;
                    521:        idp->uio = uio;
                    522:        if (ap->a_ncookies == NULL) {
                    523:                idp->cookies = NULL;
                    524:        } else {
                    525:                /*
                    526:                 * Guess the number of cookies needed.
                    527:                 */
                    528:                ncookies = uio->uio_resid / 16;
                    529:                MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
                    530:                    M_WAITOK);
                    531:                idp->cookies = cookies;
                    532:                idp->ncookies = ncookies;
                    533:        }
                    534:        idp->eofflag = 1;
                    535:        idp->curroff = uio->uio_offset;
                    536:
                    537:        if ((entryoffsetinblock = idp->curroff & bmask) &&
                    538:            (error = cd9660_bufatoff(dp, (off_t)idp->curroff, NULL, &bp))) {
                    539:                FREE(idp, M_TEMP);
                    540:                return (error);
                    541:        }
                    542:        endsearch = dp->i_size;
                    543:
                    544:        while (idp->curroff < endsearch) {
                    545:                /*
                    546:                 * If offset is on a block boundary,
                    547:                 * read the next directory block.
                    548:                 * Release previous if it exists.
                    549:                 */
                    550:                if ((idp->curroff & bmask) == 0) {
                    551:                        if (bp != NULL)
                    552:                                brelse(bp);
                    553:                        error = cd9660_bufatoff(dp, (off_t)idp->curroff,
                    554:                                             NULL, &bp);
                    555:                        if (error)
                    556:                                break;
                    557:                        entryoffsetinblock = 0;
                    558:                }
                    559:                /*
                    560:                 * Get pointer to next entry.
                    561:                 */
                    562:                ep = (struct iso_directory_record *)
                    563:                        ((char *)bp->b_data + entryoffsetinblock);
                    564:
                    565:                reclen = isonum_711(ep->length);
                    566:                if (reclen == 0) {
                    567:                        /* skip to next block, if any */
                    568:                        idp->curroff =
                    569:                            (idp->curroff & ~bmask) + imp->logical_block_size;
                    570:                        continue;
                    571:                }
                    572:
                    573:                if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
                    574:                        error = EINVAL;
                    575:                        /* illegal entry, stop */
                    576:                        break;
                    577:                }
                    578:
                    579:                if (entryoffsetinblock + reclen > imp->logical_block_size) {
                    580:                        error = EINVAL;
                    581:                        /* illegal directory, so stop looking */
                    582:                        break;
                    583:                }
                    584:
                    585:                idp->current.d_namlen = isonum_711(ep->name_len);
                    586:
                    587:                if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
                    588:                        error = EINVAL;
                    589:                        /* illegal entry, stop */
                    590:                        break;
                    591:                }
                    592:
                    593:                if (isonum_711(ep->flags)&2)
                    594:                        idp->current.d_fileno = isodirino(ep, imp);
                    595:                else
                    596:                        idp->current.d_fileno = dbtob(bp->b_blkno) +
                    597:                                entryoffsetinblock;
                    598:
                    599:                idp->curroff += reclen;
                    600:
                    601:                switch (imp->iso_ftype) {
                    602:                case ISO_FTYPE_RRIP:
                    603:                        cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
                    604:                                           &idp->current.d_fileno,imp);
                    605:                        idp->current.d_namlen = (u_char)namelen;
                    606:                        if (idp->current.d_namlen)
                    607:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
                    608:                        break;
                    609:                default:        /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
                    610:                        strlcpy(idp->current.d_name,"..",
                    611:                            sizeof idp->current.d_name);
                    612:                        if (idp->current.d_namlen == 1 && ep->name[0] == 0) {
                    613:                                idp->current.d_namlen = 1;
                    614:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
                    615:                        } else if (idp->current.d_namlen == 1 &&
                    616:                            ep->name[0] == 1) {
                    617:                                idp->current.d_namlen = 2;
                    618:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
                    619:                        } else {
                    620:                                isofntrans(ep->name,idp->current.d_namlen,
                    621:                                           idp->current.d_name, &namelen,
                    622:                                           imp->iso_ftype == ISO_FTYPE_9660,
                    623:                                           isonum_711(ep->flags) & 4,
                    624:                                           imp->joliet_level);
                    625:                                idp->current.d_namlen = (u_char)namelen;
                    626:                                if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
                    627:                                        error = iso_shipdir(idp);
                    628:                                else
                    629:                                        error = iso_uiodir(idp,&idp->current,idp->curroff);
                    630:                        }
                    631:                }
                    632:                if (error)
                    633:                        break;
                    634:
                    635:                entryoffsetinblock += reclen;
                    636:        }
                    637:
                    638:        if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
                    639:                idp->current.d_namlen = 0;
                    640:                error = iso_shipdir(idp);
                    641:        }
                    642:        if (error < 0)
                    643:                error = 0;
                    644:
                    645:        if (ap->a_ncookies != NULL) {
                    646:                if (error)
                    647:                        free(cookies, M_TEMP);
                    648:                else {
                    649:                        /*
                    650:                         * Work out the number of cookies actually used.
                    651:                         */
                    652:                        *ap->a_ncookies = ncookies - idp->ncookies;
                    653:                        *ap->a_cookies = cookies;
                    654:                }
                    655:        }
                    656:
                    657:        if (bp)
                    658:                brelse (bp);
                    659:
                    660:        uio->uio_offset = idp->uio_off;
                    661:        *ap->a_eofflag = idp->eofflag;
                    662:
                    663:        FREE(idp, M_TEMP);
                    664:
                    665:        return (error);
                    666: }
                    667:
                    668: /*
                    669:  * Return target name of a symbolic link
                    670:  * Shouldn't we get the parent vnode and read the data from there?
                    671:  * This could eventually result in deadlocks in cd9660_lookup.
                    672:  * But otherwise the block read here is in the block buffer two times.
                    673:  */
                    674: typedef struct iso_directory_record ISODIR;
                    675: typedef struct iso_node             ISONODE;
                    676: typedef struct iso_mnt              ISOMNT;
                    677: int
                    678: cd9660_readlink(v)
                    679:        void *v;
                    680: {
                    681:        struct vop_readlink_args *ap = v;
                    682:        ISONODE *ip;
                    683:        ISODIR  *dirp;
                    684:        ISOMNT  *imp;
                    685:        struct  buf *bp;
                    686:        struct  uio *uio;
                    687:        u_short symlen;
                    688:        int     error;
                    689:        char    *symname;
                    690:
                    691:        ip  = VTOI(ap->a_vp);
                    692:        imp = ip->i_mnt;
                    693:        uio = ap->a_uio;
                    694:
                    695:        if (imp->iso_ftype != ISO_FTYPE_RRIP)
                    696:                return (EINVAL);
                    697:
                    698:        /*
                    699:         * Get parents directory record block that this inode included.
                    700:         */
                    701:        error = bread(imp->im_devvp,
                    702:                      (ip->i_number >> imp->im_bshift) <<
                    703:                      (imp->im_bshift - DEV_BSHIFT),
                    704:                      imp->logical_block_size, NOCRED, &bp);
                    705:        if (error) {
                    706:                brelse(bp);
                    707:                return (EINVAL);
                    708:        }
                    709:
                    710:        /*
                    711:         * Setup the directory pointer for this inode
                    712:         */
                    713:        dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
                    714:
                    715:        /*
                    716:         * Just make sure, we have a right one....
                    717:         *   1: Check not cross boundary on block
                    718:         */
                    719:        if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
                    720:            > imp->logical_block_size) {
                    721:                brelse(bp);
                    722:                return (EINVAL);
                    723:        }
                    724:
                    725:        /*
                    726:         * Now get a buffer
                    727:         * Abuse a namei buffer for now.
                    728:         */
                    729:        if (uio->uio_segflg == UIO_SYSSPACE &&
                    730:            uio->uio_iov->iov_len >= MAXPATHLEN)
                    731:                symname = uio->uio_iov->iov_base;
                    732:        else
                    733:                symname = pool_get(&namei_pool, PR_WAITOK);
                    734:
                    735:        /*
                    736:         * Ok, we just gathering a symbolic name in SL record.
                    737:         */
                    738:        if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
                    739:                if (uio->uio_segflg != UIO_SYSSPACE ||
                    740:                    uio->uio_iov->iov_len < MAXPATHLEN)
                    741:                        pool_put(&namei_pool, symname);
                    742:                brelse(bp);
                    743:                return (EINVAL);
                    744:        }
                    745:        /*
                    746:         * Don't forget before you leave from home ;-)
                    747:         */
                    748:        brelse(bp);
                    749:
                    750:        /*
                    751:         * return with the symbolic name to caller's.
                    752:         */
                    753:        if (uio->uio_segflg != UIO_SYSSPACE ||
                    754:            uio->uio_iov->iov_len < MAXPATHLEN) {
                    755:                error = uiomove(symname, symlen, uio);
                    756:                pool_put(&namei_pool, symname);
                    757:                return (error);
                    758:        }
                    759:        uio->uio_resid -= symlen;
                    760:        (char *)uio->uio_iov->iov_base += symlen;
                    761:        uio->uio_iov->iov_len -= symlen;
                    762:        return (0);
                    763: }
                    764:
                    765: int
                    766: cd9660_link(v)
                    767:        void *v;
                    768: {
                    769:        struct vop_link_args *ap = v;
                    770:
                    771:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                    772:        vput(ap->a_dvp);
                    773:        return (EROFS);
                    774: }
                    775:
                    776: int
                    777: cd9660_symlink(v)
                    778:        void *v;
                    779: {
                    780:        struct vop_symlink_args *ap = v;
                    781:
                    782:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                    783:        vput(ap->a_dvp);
                    784:        return (EROFS);
                    785: }
                    786:
                    787: /*
                    788:  * Lock an inode.
                    789:  */
                    790: int
                    791: cd9660_lock(v)
                    792:        void *v;
                    793: {
                    794:        struct vop_lock_args *ap = v;
                    795:        struct vnode *vp = ap->a_vp;
                    796:
                    797:        return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, NULL));
                    798: }
                    799:
                    800: /*
                    801:  * Unlock an inode.
                    802:  */
                    803: int
                    804: cd9660_unlock(v)
                    805:        void *v;
                    806: {
                    807:        struct vop_unlock_args *ap = v;
                    808:        struct vnode *vp = ap->a_vp;
                    809:
                    810:        return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, NULL));
                    811: }
                    812:
                    813: /*
                    814:  * Calculate the logical to physical mapping if not done already,
                    815:  * then call the device strategy routine.
                    816:  */
                    817: int
                    818: cd9660_strategy(v)
                    819:        void *v;
                    820: {
                    821:        struct vop_strategy_args *ap = v;
                    822:        struct buf *bp = ap->a_bp;
                    823:        struct vnode *vp = bp->b_vp;
                    824:        struct iso_node *ip;
                    825:        int error;
                    826:        int s;
                    827:
                    828:        ip = VTOI(vp);
                    829:        if (vp->v_type == VBLK || vp->v_type == VCHR)
                    830:                panic("cd9660_strategy: spec");
                    831:        if (bp->b_blkno == bp->b_lblkno) {
                    832:                error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
                    833:                if (error) {
                    834:                        bp->b_error = error;
                    835:                        bp->b_flags |= B_ERROR;
                    836:                        s = splbio();
                    837:                        biodone(bp);
                    838:                        splx(s);
                    839:                        return (error);
                    840:                }
                    841:                if ((long)bp->b_blkno == -1)
                    842:                        clrbuf(bp);
                    843:        }
                    844:        if ((long)bp->b_blkno == -1) {
                    845:                s = splbio();
                    846:                biodone(bp);
                    847:                splx(s);
                    848:                return (0);
                    849:        }
                    850:        vp = ip->i_devvp;
                    851:        bp->b_dev = vp->v_rdev;
                    852:        VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
                    853:        return (0);
                    854: }
                    855:
                    856: /*
                    857:  * Print out the contents of an inode.
                    858:  */
                    859: /*ARGSUSED*/
                    860: int
                    861: cd9660_print(v)
                    862:        void *v;
                    863: {
                    864:        printf("tag VT_ISOFS, isofs vnode\n");
                    865:        return (0);
                    866: }
                    867:
                    868: /*
                    869:  * Check for a locked inode.
                    870:  */
                    871: int
                    872: cd9660_islocked(v)
                    873:        void *v;
                    874: {
                    875:        struct vop_islocked_args *ap = v;
                    876:
                    877:        return (lockstatus(&VTOI(ap->a_vp)->i_lock));
                    878: }
                    879:
                    880: /*
                    881:  * Return POSIX pathconf information applicable to cd9660 filesystems.
                    882:  */
                    883: int
                    884: cd9660_pathconf(v)
                    885:        void *v;
                    886: {
                    887:        struct vop_pathconf_args *ap = v;
                    888:        switch (ap->a_name) {
                    889:        case _PC_LINK_MAX:
                    890:                *ap->a_retval = 1;
                    891:                return (0);
                    892:        case _PC_NAME_MAX:
                    893:                if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
                    894:                        *ap->a_retval = NAME_MAX;
                    895:                else
                    896:                        *ap->a_retval = 37;
                    897:                return (0);
                    898:        case _PC_PATH_MAX:
                    899:                *ap->a_retval = PATH_MAX;
                    900:                return (0);
                    901:        case _PC_PIPE_BUF:
                    902:                *ap->a_retval = PIPE_BUF;
                    903:                return (0);
                    904:        case _PC_CHOWN_RESTRICTED:
                    905:                *ap->a_retval = 1;
                    906:                return (0);
                    907:        case _PC_NO_TRUNC:
                    908:                *ap->a_retval = 1;
                    909:                return (0);
                    910:        default:
                    911:                return (EINVAL);
                    912:        }
                    913:        /* NOTREACHED */
                    914: }
                    915:
                    916: /*
                    917:  * Global vfs data structures for isofs
                    918:  */
                    919: #define        cd9660_create   eopnotsupp
                    920: #define        cd9660_mknod    eopnotsupp
                    921: #define        cd9660_write    eopnotsupp
                    922: #define        cd9660_fsync    nullop
                    923: #define        cd9660_remove   eopnotsupp
                    924: #define        cd9660_rename   eopnotsupp
                    925: #define        cd9660_mkdir    eopnotsupp
                    926: #define        cd9660_rmdir    eopnotsupp
                    927: #define        cd9660_advlock  eopnotsupp
                    928: #define        cd9660_valloc   eopnotsupp
                    929: #define        cd9660_vfree    eopnotsupp
                    930: #define        cd9660_truncate eopnotsupp
                    931: #define        cd9660_update   eopnotsupp
                    932: #define        cd9660_bwrite   eopnotsupp
                    933: #define cd9660_revoke   vop_generic_revoke
                    934:
                    935: /*
                    936:  * Global vfs data structures for cd9660
                    937:  */
                    938: int (**cd9660_vnodeop_p)(void *);
                    939: struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
                    940:        { &vop_default_desc, vn_default_error },
                    941:        { &vop_lookup_desc, cd9660_lookup },    /* lookup */
                    942:        { &vop_create_desc, cd9660_create },    /* create */
                    943:        { &vop_mknod_desc, cd9660_mknod },      /* mknod */
                    944:        { &vop_open_desc, cd9660_open },        /* open */
                    945:        { &vop_close_desc, cd9660_close },      /* close */
                    946:        { &vop_access_desc, cd9660_access },    /* access */
                    947:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
                    948:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
                    949:        { &vop_read_desc, cd9660_read },        /* read */
                    950:        { &vop_write_desc, cd9660_write },      /* write */
                    951:        { &vop_ioctl_desc, cd9660_ioctl },      /* ioctl */
                    952:        { &vop_poll_desc, cd9660_poll },        /* poll */
                    953:        { &vop_revoke_desc, cd9660_revoke },    /* revoke */
                    954:        { &vop_fsync_desc, cd9660_fsync },      /* fsync */
                    955:        { &vop_remove_desc, cd9660_remove },    /* remove */
                    956:        { &vop_link_desc, cd9660_link },        /* link */
                    957:        { &vop_rename_desc, cd9660_rename },    /* rename */
                    958:        { &vop_mkdir_desc, cd9660_mkdir },      /* mkdir */
                    959:        { &vop_rmdir_desc, cd9660_rmdir },      /* rmdir */
                    960:        { &vop_symlink_desc, cd9660_symlink },  /* symlink */
                    961:        { &vop_readdir_desc, cd9660_readdir },  /* readdir */
                    962:        { &vop_readlink_desc, cd9660_readlink },/* readlink */
                    963:        { &vop_abortop_desc, vop_generic_abortop },     /* abortop */
                    964:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
                    965:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
                    966:        { &vop_lock_desc, cd9660_lock },        /* lock */
                    967:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
                    968:        { &vop_bmap_desc, cd9660_bmap },        /* bmap */
                    969:        { &vop_strategy_desc, cd9660_strategy },/* strategy */
                    970:        { &vop_print_desc, cd9660_print },      /* print */
                    971:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
                    972:        { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */
                    973:        { &vop_advlock_desc, cd9660_advlock },  /* advlock */
                    974:        { &vop_bwrite_desc, vop_generic_bwrite },
                    975:        { NULL, NULL }
                    976: };
                    977: struct vnodeopv_desc cd9660_vnodeop_opv_desc =
                    978:        { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
                    979:
                    980: /*
                    981:  * Special device vnode ops
                    982:  */
                    983: int (**cd9660_specop_p)(void *);
                    984: struct vnodeopv_entry_desc cd9660_specop_entries[] = {
                    985:        { &vop_default_desc, spec_vnoperate },
                    986:        { &vop_access_desc, cd9660_access },    /* access */
                    987:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
                    988:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
                    989:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
                    990:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
                    991:        { &vop_lock_desc, cd9660_lock },        /* lock */
                    992:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
                    993:        { &vop_print_desc, cd9660_print },      /* print */
                    994:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
                    995:        { NULL, NULL }
                    996: };
                    997: struct vnodeopv_desc cd9660_specop_opv_desc =
                    998:        { &cd9660_specop_p, cd9660_specop_entries };
                    999:
                   1000: #ifdef FIFO
                   1001: int (**cd9660_fifoop_p)(void *);
                   1002: struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
                   1003:        { &vop_default_desc, fifo_vnoperate },
                   1004:        { &vop_access_desc, cd9660_access },    /* access */
                   1005:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
                   1006:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
                   1007:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
                   1008:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
                   1009:        { &vop_lock_desc, cd9660_lock },        /* lock */
                   1010:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
                   1011:        { &vop_print_desc, cd9660_print },      /* print */
                   1012:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
                   1013:        { &vop_bwrite_desc, vop_generic_bwrite },
                   1014:        { NULL, NULL }
                   1015: };
                   1016: struct vnodeopv_desc cd9660_fifoop_opv_desc =
                   1017:        { &cd9660_fifoop_p, cd9660_fifoop_entries };
                   1018: #endif /* FIFO */

CVSweb