|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1990, 1992 Jan-Simon Pendry ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Jan-Simon Pendry. ! 7: * ! 8: * Redistribution and use in source and binary forms, with or without ! 9: * modification, are permitted provided that the following conditions ! 10: * are met: ! 11: * 1. Redistributions of source code must retain the above copyright ! 12: * notice, this list of conditions and the following disclaimer. ! 13: * 2. Redistributions in binary form must reproduce the above copyright ! 14: * notice, this list of conditions and the following disclaimer in the ! 15: * documentation and/or other materials provided with the distribution. ! 16: * 3. All advertising materials mentioning features or use of this software ! 17: * must display the following acknowledgement: ! 18: * This product includes software developed by the University of ! 19: * California, Berkeley and its contributors. ! 20: * 4. 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: * $Id: fdesc_vnops.c,v 1.3 1993/03/30 05:16:56 cgd Exp $ ! 37: */ ! 38: ! 39: /* ! 40: * /dev/fd Filesystem ! 41: */ ! 42: ! 43: #include "param.h" ! 44: #include "systm.h" ! 45: #include "types.h" ! 46: #include "time.h" ! 47: #include "proc.h" ! 48: #include "resourcevar.h" ! 49: #include "filedesc.h" ! 50: #include "vnode.h" ! 51: #include "file.h" ! 52: #include "stat.h" ! 53: #include "mount.h" ! 54: #include "namei.h" ! 55: #include "buf.h" ! 56: #include "miscfs/fdesc/fdesc.h" ! 57: ! 58: #include "../ufs/dir.h" /* For readdir() XXX */ ! 59: ! 60: /* ! 61: * vp is the current namei directory ! 62: * ndp is the name to locate in that directory... ! 63: */ ! 64: fdesc_lookup(dvp, ndp, p) ! 65: struct vnode *dvp; ! 66: struct nameidata *ndp; ! 67: struct proc *p; ! 68: { ! 69: char *pname = ndp->ni_ptr; ! 70: int nfiles = p->p_fd->fd_nfiles; ! 71: unsigned fd; ! 72: int error; ! 73: struct vnode *fvp; ! 74: ! 75: #ifdef FDESC_DIAGNOSTIC ! 76: printf("fdesc_lookup(%s)\n", pname); ! 77: #endif ! 78: if (ndp->ni_namelen == 1 && *pname == '.') { ! 79: ndp->ni_dvp = dvp; ! 80: ndp->ni_vp = dvp; ! 81: VREF(dvp); ! 82: /*VOP_LOCK(dvp);*/ ! 83: return (0); ! 84: } ! 85: ! 86: fd = 0; ! 87: while (*pname >= '0' && *pname <= '9') { ! 88: fd = 10 * fd + *pname++ - '0'; ! 89: if (fd >= nfiles) ! 90: break; ! 91: } ! 92: ! 93: #ifdef FDESC_DIAGNOSTIC ! 94: printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname); ! 95: #endif ! 96: if (*pname == '/') { ! 97: error = ENOTDIR; ! 98: goto bad; ! 99: } ! 100: ! 101: if (*pname != '\0') { ! 102: error = ENOENT; ! 103: goto bad; ! 104: } ! 105: ! 106: if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { ! 107: error = EBADF; ! 108: goto bad; ! 109: } ! 110: ! 111: #ifdef FDESC_DIAGNOSTIC ! 112: printf("fdesc_lookup: allocate new vnode\n"); ! 113: #endif ! 114: error = getnewvnode(VT_UFS, dvp->v_mount, &fdesc_vnodeops, &fvp); ! 115: if (error) ! 116: goto bad; ! 117: VTOFDESC(fvp)->f_fd = fd; ! 118: /*VTOFDESC(fvp)->f_isroot = 0;*/ ! 119: ndp->ni_dvp = dvp; ! 120: ndp->ni_vp = fvp; ! 121: #ifdef FDESC_DIAGNOSTIC ! 122: printf("fdesc_lookup: newvp = %x\n", fvp); ! 123: #endif ! 124: return (0); ! 125: ! 126: bad:; ! 127: ndp->ni_dvp = dvp; ! 128: ndp->ni_vp = NULL; ! 129: #ifdef FDESC_DIAGNOSTIC ! 130: printf("fdesc_lookup: error = %d\n", error); ! 131: #endif ! 132: return (error); ! 133: } ! 134: ! 135: fdesc_open(vp, mode, cred, p) ! 136: struct vnode *vp; ! 137: int mode; ! 138: struct ucred *cred; ! 139: struct proc *p; ! 140: { ! 141: int error; ! 142: struct filedesc *fdp; ! 143: struct file *fp; ! 144: int dfd; ! 145: int fd; ! 146: ! 147: /* ! 148: * Can always open the root (modulo perms) ! 149: */ ! 150: if (vp->v_flag & VROOT) ! 151: return (0); ! 152: ! 153: /* ! 154: * XXX Kludge: set p->p_dupfd to contain the value of the ! 155: * the file descriptor being sought for duplication. The error ! 156: * return ensures that the vnode for this device will be released ! 157: * by vn_open. Open will detect this special error and take the ! 158: * actions in dupfdopen. Other callers of vn_open or VOP_OPEN ! 159: * will simply report the error. ! 160: */ ! 161: p->p_dupfd = VTOFDESC(vp)->f_fd; /* XXX */ ! 162: return (ENODEV); ! 163: } ! 164: ! 165: static int ! 166: fdesc_attr(fd, vap, cred, p) ! 167: int fd; ! 168: struct vattr *vap; ! 169: struct ucred *cred; ! 170: struct proc *p; ! 171: { ! 172: struct filedesc *fdp = p->p_fd; ! 173: struct file *fp; ! 174: int error; ! 175: ! 176: #ifdef FDESC_DIAGNOSTIC ! 177: printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); ! 178: #endif ! 179: if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { ! 180: #ifdef FDESC_DIAGNOSTIC ! 181: printf("fdesc_attr: fp = %x (EBADF)\n", fp); ! 182: #endif ! 183: return (EBADF); ! 184: } ! 185: ! 186: /* ! 187: * Can stat the underlying vnode, but not sockets because ! 188: * they don't use struct vattrs. Well, we could convert from ! 189: * a struct stat back to a struct vattr, later... ! 190: */ ! 191: switch (fp->f_type) { ! 192: case DTYPE_VNODE: ! 193: error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); ! 194: break; ! 195: ! 196: case DTYPE_SOCKET: ! 197: error = EOPNOTSUPP; ! 198: break; ! 199: ! 200: default: ! 201: panic("fdesc attr"); ! 202: break; ! 203: } ! 204: ! 205: #ifdef FDESC_DIAGNOSTIC ! 206: printf("fdesc_attr: returns error %d\n", error); ! 207: #endif ! 208: return (error); ! 209: } ! 210: ! 211: fdesc_getattr(vp, vap, cred, p) ! 212: struct vnode *vp; ! 213: struct vattr *vap; ! 214: struct ucred *cred; ! 215: struct proc *p; ! 216: { ! 217: unsigned fd; ! 218: int error; ! 219: ! 220: if (vp->v_flag & VROOT) { ! 221: #ifdef FDESC_DIAGNOSTIC ! 222: printf("fdesc_getattr: stat rootdir\n"); ! 223: #endif ! 224: bzero((caddr_t) vap, sizeof(*vap)); ! 225: vattr_null(vap); ! 226: vap->va_type = VDIR; ! 227: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; ! 228: vap->va_nlink = 2; ! 229: vap->va_uid = 0; ! 230: vap->va_gid = 0; ! 231: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; ! 232: vap->va_fileid = 2; ! 233: /* vap->va_qsize = 0; */ ! 234: vap->va_size = DEV_BSIZE; ! 235: vap->va_blocksize = DEV_BSIZE; ! 236: microtime(&vap->va_atime); ! 237: vap->va_mtime = vap->va_atime; ! 238: vap->va_ctime = vap->va_ctime; ! 239: vap->va_gen = 0; ! 240: vap->va_flags = 0; ! 241: vap->va_rdev = 0; ! 242: /* vap->va_qbytes = 0; */ ! 243: vap->va_bytes = 0; ! 244: return (0); ! 245: } ! 246: ! 247: fd = VTOFDESC(vp)->f_fd; ! 248: error = fdesc_attr(fd, vap, cred, p); ! 249: if (error == 0) ! 250: vp->v_type = vap->va_type; ! 251: return (error); ! 252: } ! 253: ! 254: fdesc_setattr(vp, vap, cred, p) ! 255: struct vnode *vp; ! 256: struct vattr *vap; ! 257: struct ucred *cred; ! 258: struct proc *p; ! 259: { ! 260: struct filedesc *fdp = p->p_fd; ! 261: struct file *fp; ! 262: unsigned fd; ! 263: int error; ! 264: ! 265: /* ! 266: * Can't mess with the root vnode ! 267: */ ! 268: if (vp->v_flag & VROOT) ! 269: return (EACCES); ! 270: ! 271: fd = VTOFDESC(vp)->f_fd; ! 272: #ifdef FDESC_DIAGNOSTIC ! 273: printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); ! 274: #endif ! 275: if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { ! 276: #ifdef FDESC_DIAGNOSTIC ! 277: printf("fdesc_setattr: fp = %x (EBADF)\n", fp); ! 278: #endif ! 279: return (EBADF); ! 280: } ! 281: ! 282: /* ! 283: * Can setattr the underlying vnode, but not sockets! ! 284: */ ! 285: switch (fp->f_type) { ! 286: case DTYPE_VNODE: ! 287: error = VOP_SETATTR((struct vnode *) fp->f_data, vap, cred, p); ! 288: break; ! 289: ! 290: case DTYPE_SOCKET: ! 291: error = EOPNOTSUPP; ! 292: break; ! 293: ! 294: default: ! 295: panic("fdesc setattr"); ! 296: break; ! 297: } ! 298: ! 299: #ifdef FDESC_DIAGNOSTIC ! 300: printf("fdesc_setattr: returns error %d\n", error); ! 301: #endif ! 302: return (error); ! 303: } ! 304: ! 305: fdesc_readdir(vp, uio, cred, eofflagp) ! 306: struct vnode *vp; ! 307: struct uio *uio; ! 308: struct ucred *cred; ! 309: int *eofflagp; ! 310: { ! 311: struct filedesc *fdp; ! 312: int ind, i; ! 313: int error; ! 314: ! 315: #define UIO_MX 16 ! 316: ! 317: fdp = uio->uio_procp->p_fd; ! 318: ind = uio->uio_offset / UIO_MX; ! 319: error = 0; ! 320: while (uio->uio_resid > 0) { ! 321: struct direct d; ! 322: struct direct *dp = &d; ! 323: ! 324: if (ind < 2) { /* . or .. */ ! 325: bzero((caddr_t) dp, UIO_MX); ! 326: if (ind == 0) { ! 327: strcpy(dp->d_name, "."); ! 328: dp->d_namlen = 1; ! 329: } else if (ind == 1) { ! 330: strcpy(dp->d_name, ".."); ! 331: dp->d_namlen = 2; ! 332: } else ! 333: panic("fdesc: ind is negative!"); ! 334: ! 335: dp->d_reclen = UIO_MX; ! 336: dp->d_ino = 2; ! 337: ! 338: /* ! 339: * And ship to userland ! 340: */ ! 341: error = uiomove((caddr_t) dp, UIO_MX, uio); ! 342: if (error) ! 343: break; ! 344: ! 345: ind++; ! 346: continue; ! 347: } ! 348: i = ind - 2; ! 349: if (i >= fdp->fd_nfiles) { ! 350: *eofflagp = 1; ! 351: break; ! 352: } ! 353: if (fdp->fd_ofiles[i] != NULL) { ! 354: struct direct d; ! 355: struct direct *dp = &d; ! 356: char *cp = dp->d_name; ! 357: #ifdef FDESC_FILEID ! 358: struct vattr va; ! 359: #endif ! 360: int j; ! 361: ! 362: bzero((caddr_t) dp, UIO_MX); ! 363: ! 364: /* ! 365: * Generate an ASCII representation of the name. ! 366: * This can cope with fds in the range 0..99999 ! 367: */ ! 368: cp++; ! 369: if (i > 10) cp++; ! 370: if (i > 100) cp++; ! 371: if (i > 1000) cp++; ! 372: if (i > 10000) cp++; ! 373: if (i > 100000) panic("fdesc_readdir"); ! 374: dp->d_namlen = cp - dp->d_name; ! 375: *cp = '\0'; ! 376: j = i; ! 377: do { ! 378: *--cp = j % 10 + '0'; ! 379: j /= 10; ! 380: } while (j > 0); ! 381: /* ! 382: * Fill in the remaining fields ! 383: */ ! 384: dp->d_reclen = UIO_MX; ! 385: dp->d_ino = i + 3; ! 386: #ifdef FDESC_FILEID ! 387: /* ! 388: * If we want the file ids to match the ! 389: * we must call getattr on the underlying file. ! 390: * fdesc_attr may return an error, in which case ! 391: * we ignore the returned file id. ! 392: */ ! 393: error = fdesc_attr(i, &va, cred, p); ! 394: if (error == 0) ! 395: dp->d_ino = va.va_fileid; ! 396: #endif ! 397: /* ! 398: * And ship to userland ! 399: */ ! 400: error = uiomove((caddr_t) dp, UIO_MX, uio); ! 401: if (error) ! 402: break; ! 403: } ! 404: ind++; ! 405: } ! 406: ! 407: uio->uio_offset = ind * UIO_MX; ! 408: return (error); ! 409: } ! 410: ! 411: fdesc_inactive(vp, p) ! 412: struct vnode *vp; ! 413: struct proc *p; ! 414: { ! 415: /* ! 416: * Clear out the v_type field to avoid ! 417: * nasty things happening in vgone(). ! 418: */ ! 419: vp->v_type = VNON; ! 420: #ifdef FDESC_DIAGNOSTIC ! 421: printf("fdesc_inactive(%x)\n", vp); ! 422: #endif ! 423: return (0); ! 424: } ! 425: ! 426: /* ! 427: * Print out the contents of a /dev/fd vnode. ! 428: */ ! 429: /* ARGSUSED */ ! 430: fdesc_print(vp) ! 431: struct vnode *vp; ! 432: { ! 433: printf("tag VT_NON, fdesc vnode\n"); ! 434: } ! 435: ! 436: /* ! 437: * /dev/fd vnode unsupported operation ! 438: */ ! 439: fdesc_enotsupp() ! 440: { ! 441: return (EOPNOTSUPP); ! 442: } ! 443: ! 444: /* ! 445: * /dev/fd "should never get here" operation ! 446: */ ! 447: fdesc_badop() ! 448: { ! 449: panic("fdesc: bad op"); ! 450: /* NOTREACHED */ ! 451: } ! 452: ! 453: /* ! 454: * /dev/fd vnode null operation ! 455: */ ! 456: fdesc_nullop() ! 457: { ! 458: return (0); ! 459: } ! 460: ! 461: #define fdesc_create ((int (*) __P(( \ ! 462: struct nameidata *ndp, \ ! 463: struct vattr *vap, \ ! 464: struct proc *p))) fdesc_enotsupp) ! 465: #define fdesc_mknod ((int (*) __P(( \ ! 466: struct nameidata *ndp, \ ! 467: struct vattr *vap, \ ! 468: struct ucred *cred, \ ! 469: struct proc *p))) fdesc_enotsupp) ! 470: #define fdesc_close ((int (*) __P(( \ ! 471: struct vnode *vp, \ ! 472: int fflag, \ ! 473: struct ucred *cred, \ ! 474: struct proc *p))) nullop) ! 475: #define fdesc_access ((int (*) __P(( \ ! 476: struct vnode *vp, \ ! 477: int mode, \ ! 478: struct ucred *cred, \ ! 479: struct proc *p))) nullop) ! 480: #define fdesc_read ((int (*) __P(( \ ! 481: struct vnode *vp, \ ! 482: struct uio *uio, \ ! 483: int ioflag, \ ! 484: struct ucred *cred))) fdesc_enotsupp) ! 485: #define fdesc_write ((int (*) __P(( \ ! 486: struct vnode *vp, \ ! 487: struct uio *uio, \ ! 488: int ioflag, \ ! 489: struct ucred *cred))) fdesc_enotsupp) ! 490: #define fdesc_ioctl ((int (*) __P(( \ ! 491: struct vnode *vp, \ ! 492: int command, \ ! 493: caddr_t data, \ ! 494: int fflag, \ ! 495: struct ucred *cred, \ ! 496: struct proc *p))) fdesc_enotsupp) ! 497: #define fdesc_select ((int (*) __P(( \ ! 498: struct vnode *vp, \ ! 499: int which, \ ! 500: int fflags, \ ! 501: struct ucred *cred, \ ! 502: struct proc *p))) fdesc_enotsupp) ! 503: #define fdesc_mmap ((int (*) __P(( \ ! 504: struct vnode *vp, \ ! 505: int fflags, \ ! 506: struct ucred *cred, \ ! 507: struct proc *p))) fdesc_enotsupp) ! 508: #define fdesc_fsync ((int (*) __P(( \ ! 509: struct vnode *vp, \ ! 510: int fflags, \ ! 511: struct ucred *cred, \ ! 512: int waitfor, \ ! 513: struct proc *p))) nullop) ! 514: #define fdesc_seek ((int (*) __P(( \ ! 515: struct vnode *vp, \ ! 516: off_t oldoff, \ ! 517: off_t newoff, \ ! 518: struct ucred *cred))) nullop) ! 519: #define fdesc_remove ((int (*) __P(( \ ! 520: struct nameidata *ndp, \ ! 521: struct proc *p))) fdesc_enotsupp) ! 522: #define fdesc_link ((int (*) __P(( \ ! 523: struct vnode *vp, \ ! 524: struct nameidata *ndp, \ ! 525: struct proc *p))) fdesc_enotsupp) ! 526: #define fdesc_rename ((int (*) __P(( \ ! 527: struct nameidata *fndp, \ ! 528: struct nameidata *tdnp, \ ! 529: struct proc *p))) fdesc_enotsupp) ! 530: #define fdesc_mkdir ((int (*) __P(( \ ! 531: struct nameidata *ndp, \ ! 532: struct vattr *vap, \ ! 533: struct proc *p))) fdesc_enotsupp) ! 534: #define fdesc_rmdir ((int (*) __P(( \ ! 535: struct nameidata *ndp, \ ! 536: struct proc *p))) fdesc_enotsupp) ! 537: #define fdesc_symlink ((int (*) __P(( \ ! 538: struct nameidata *ndp, \ ! 539: struct vattr *vap, \ ! 540: char *target, \ ! 541: struct proc *p))) fdesc_enotsupp) ! 542: #define fdesc_readlink ((int (*) __P(( \ ! 543: struct vnode *vp, \ ! 544: struct uio *uio, \ ! 545: struct ucred *cred))) fdesc_enotsupp) ! 546: #define fdesc_abortop ((int (*) __P(( \ ! 547: struct nameidata *ndp))) nullop) ! 548: #ifdef FDESC_DIAGNOSTIC ! 549: int fdesc_reclaim(vp) ! 550: struct vnode *vp; ! 551: { ! 552: printf("fdesc_reclaim(%x)\n", vp); ! 553: return (0); ! 554: } ! 555: #else ! 556: #define fdesc_reclaim ((int (*) __P(( \ ! 557: struct vnode *vp))) nullop) ! 558: #endif ! 559: #define fdesc_lock ((int (*) __P(( \ ! 560: struct vnode *vp))) nullop) ! 561: #define fdesc_unlock ((int (*) __P(( \ ! 562: struct vnode *vp))) nullop) ! 563: #define fdesc_bmap ((int (*) __P(( \ ! 564: struct vnode *vp, \ ! 565: daddr_t bn, \ ! 566: struct vnode **vpp, \ ! 567: daddr_t *bnp))) fdesc_badop) ! 568: #define fdesc_strategy ((int (*) __P(( \ ! 569: struct buf *bp))) fdesc_badop) ! 570: #define fdesc_islocked ((int (*) __P(( \ ! 571: struct vnode *vp))) nullop) ! 572: #define fdesc_advlock ((int (*) __P(( \ ! 573: struct vnode *vp, \ ! 574: caddr_t id, \ ! 575: int op, \ ! 576: struct flock *fl, \ ! 577: int flags))) fdesc_enotsupp) ! 578: ! 579: struct vnodeops fdesc_vnodeops = { ! 580: fdesc_lookup, /* lookup */ ! 581: fdesc_create, /* create */ ! 582: fdesc_mknod, /* mknod */ ! 583: fdesc_open, /* open */ ! 584: fdesc_close, /* close */ ! 585: fdesc_access, /* access */ ! 586: fdesc_getattr, /* getattr */ ! 587: fdesc_setattr, /* setattr */ ! 588: fdesc_read, /* read */ ! 589: fdesc_write, /* write */ ! 590: fdesc_ioctl, /* ioctl */ ! 591: fdesc_select, /* select */ ! 592: fdesc_mmap, /* mmap */ ! 593: fdesc_fsync, /* fsync */ ! 594: fdesc_seek, /* seek */ ! 595: fdesc_remove, /* remove */ ! 596: fdesc_link, /* link */ ! 597: fdesc_rename, /* rename */ ! 598: fdesc_mkdir, /* mkdir */ ! 599: fdesc_rmdir, /* rmdir */ ! 600: fdesc_symlink, /* symlink */ ! 601: fdesc_readdir, /* readdir */ ! 602: fdesc_readlink, /* readlink */ ! 603: fdesc_abortop, /* abortop */ ! 604: fdesc_inactive, /* inactive */ ! 605: fdesc_reclaim, /* reclaim */ ! 606: fdesc_lock, /* lock */ ! 607: fdesc_unlock, /* unlock */ ! 608: fdesc_bmap, /* bmap */ ! 609: fdesc_strategy, /* strategy */ ! 610: fdesc_print, /* print */ ! 611: fdesc_islocked, /* islocked */ ! 612: fdesc_advlock, /* advlock */ ! 613: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.