Annotation of sys/isofs/cd9660/cd9660_vnops.c, Revision 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