Home | History | Annotate | Line # | Download | only in fdesc
fdesc_vnops.c revision 1.6.2.1
      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.6.2.1 1993/11/14 22:34:41 mycroft Exp $
     37  */
     38 
     39 /*
     40  * /dev/fd Filesystem
     41  */
     42 
     43 #include <sys/param.h>
     44 #include <sys/systm.h>
     45 #include <sys/types.h>
     46 #include <sys/time.h>
     47 #include <sys/proc.h>
     48 #include <sys/resourcevar.h>
     49 #include <sys/filedesc.h>
     50 #include <sys/vnode.h>
     51 #include <sys/file.h>
     52 #include <sys/stat.h>
     53 #include <sys/mount.h>
     54 #include <sys/namei.h>
     55 #include <sys/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_FDESC, 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, cookies, ncookies)
    306 	struct vnode *vp;
    307 	struct uio *uio;
    308 	struct ucred *cred;
    309 	int *eofflagp;
    310 	u_int *cookies;
    311 	int ncookies;
    312 {
    313 	struct filedesc *fdp;
    314 	int ind, i;
    315 	int error;
    316 
    317 #define UIO_MX 16
    318 
    319 	fdp = uio->uio_procp->p_fd;
    320 	ind = uio->uio_offset / UIO_MX;
    321 	error = 0;
    322 	while (uio->uio_resid > 0 && (!cookies || ncookies > 0)) {
    323 		struct direct d;
    324 		struct direct *dp = &d;
    325 
    326 	        if (ind < 2) { /* . or .. */
    327 		  bzero((caddr_t) dp, UIO_MX);
    328 		  if (ind == 0) {
    329 		    strcpy(dp->d_name, ".");
    330 		    dp->d_namlen = 1;
    331 		  } else if (ind == 1) {
    332 		    strcpy(dp->d_name, "..");
    333 		    dp->d_namlen = 2;
    334 		  } else
    335 		    panic("fdesc: ind is negative!");
    336 
    337 		  dp->d_reclen = UIO_MX;
    338 		  dp->d_ino = 2;
    339 
    340 		  /*
    341 		   * And ship to userland
    342 		   */
    343 		  error = uiomove((caddr_t) dp, UIO_MX, uio);
    344 		  if (error)
    345 		    break;
    346 
    347 		  ind++;
    348 		  if (cookies) {
    349 			  *cookies++ = ind * UIO_MX;
    350 			  ncookies--;
    351 		  }
    352 		  continue;
    353 		}
    354 	        i = ind - 2;
    355 		if (i >= fdp->fd_nfiles) {
    356 			*eofflagp = 1;
    357 			break;
    358 		}
    359 		if (fdp->fd_ofiles[i] != NULL) {
    360 			struct direct d;
    361 			struct direct *dp = &d;
    362 			char *cp = dp->d_name;
    363 #ifdef FDESC_FILEID
    364 			struct vattr va;
    365 #endif
    366 			int j;
    367 
    368 			bzero((caddr_t) dp, UIO_MX);
    369 
    370 			/*
    371 			 * Generate an ASCII representation of the name.
    372 			 * This can cope with fds in the range 0..99999
    373 			 */
    374 			cp++;
    375 			if (i > 10) cp++;
    376 			if (i > 100) cp++;
    377 			if (i > 1000) cp++;
    378 			if (i > 10000) cp++;
    379 			if (i > 100000) panic("fdesc_readdir");
    380 			dp->d_namlen = cp - dp->d_name;
    381 			*cp = '\0';
    382 			j = i;
    383 			do {
    384 				*--cp = j % 10 + '0';
    385 				j /= 10;
    386 			} while (j > 0);
    387 			/*
    388 			 * Fill in the remaining fields
    389 			 */
    390 			dp->d_reclen = UIO_MX;
    391 			dp->d_ino = i + 3;
    392 #ifdef FDESC_FILEID
    393 			/*
    394 			 * If we want the file ids to match the
    395 			 * we must call getattr on the underlying file.
    396 			 * fdesc_attr may return an error, in which case
    397 			 * we ignore the returned file id.
    398 			 */
    399 			error = fdesc_attr(i, &va, cred, p);
    400 			if (error == 0)
    401 				dp->d_ino = va.va_fileid;
    402 #endif
    403 			/*
    404 			 * And ship to userland
    405 			 */
    406 			error = uiomove((caddr_t) dp, UIO_MX, uio);
    407 			if (error)
    408 				break;
    409 			if (cookies) {
    410 				*cookies++ = (ind + 1) * UIO_MX;
    411 				ncookies--;
    412 			}
    413 		}
    414 		ind++;
    415 	}
    416 
    417 	uio->uio_offset = ind * UIO_MX;
    418 	return (error);
    419 }
    420 
    421 fdesc_inactive(vp, p)
    422 	struct vnode *vp;
    423 	struct proc *p;
    424 {
    425 	/*
    426 	 * Clear out the v_type field to avoid
    427 	 * nasty things happening in vgone().
    428 	 */
    429 	vp->v_type = VNON;
    430 #ifdef FDESC_DIAGNOSTIC
    431 	printf("fdesc_inactive(%x)\n", vp);
    432 #endif
    433 	return (0);
    434 }
    435 
    436 /*
    437  * Print out the contents of a /dev/fd vnode.
    438  */
    439 /* ARGSUSED */
    440 void
    441 fdesc_print(vp)
    442 	struct vnode *vp;
    443 {
    444 	printf("tag VT_FDESC, fdesc vnode\n");
    445 }
    446 
    447 /*
    448  * /dev/fd vnode unsupported operation
    449  */
    450 fdesc_enotsupp()
    451 {
    452 	return (EOPNOTSUPP);
    453 }
    454 
    455 /*
    456  * /dev/fd "should never get here" operation
    457  */
    458 fdesc_badop()
    459 {
    460 	panic("fdesc: bad op");
    461 	/* NOTREACHED */
    462 }
    463 
    464 /*
    465  * /dev/fd vnode null operation
    466  */
    467 fdesc_nullop()
    468 {
    469 	return (0);
    470 }
    471 
    472 #define fdesc_create ((int (*) __P(( \
    473 		struct nameidata *ndp, \
    474 		struct vattr *vap, \
    475 		struct proc *p))) fdesc_enotsupp)
    476 #define fdesc_mknod ((int (*) __P(( \
    477 		struct nameidata *ndp, \
    478 		struct vattr *vap, \
    479 		struct ucred *cred, \
    480 		struct proc *p))) fdesc_enotsupp)
    481 #define fdesc_close ((int (*) __P(( \
    482 		struct vnode *vp, \
    483 		int fflag, \
    484 		struct ucred *cred, \
    485 		struct proc *p))) nullop)
    486 #define fdesc_access ((int (*) __P(( \
    487 		struct vnode *vp, \
    488 		int mode, \
    489 		struct ucred *cred, \
    490 		struct proc *p))) nullop)
    491 #define	fdesc_read ((int (*) __P(( \
    492 		struct vnode *vp, \
    493 		struct uio *uio, \
    494 		int ioflag, \
    495 		struct ucred *cred))) fdesc_enotsupp)
    496 #define	fdesc_write ((int (*) __P(( \
    497 		struct vnode *vp, \
    498 		struct uio *uio, \
    499 		int ioflag, \
    500 		struct ucred *cred))) fdesc_enotsupp)
    501 #define	fdesc_ioctl ((int (*) __P(( \
    502 		struct vnode *vp, \
    503 		int command, \
    504 		caddr_t data, \
    505 		int fflag, \
    506 		struct ucred *cred, \
    507 		struct proc *p))) fdesc_enotsupp)
    508 #define	fdesc_select ((int (*) __P(( \
    509 		struct vnode *vp, \
    510 		int which, \
    511 		int fflags, \
    512 		struct ucred *cred, \
    513 		struct proc *p))) fdesc_enotsupp)
    514 #define fdesc_mmap ((int (*) __P(( \
    515 		struct vnode *vp, \
    516 		int fflags, \
    517 		struct ucred *cred, \
    518 		struct proc *p))) fdesc_enotsupp)
    519 #define fdesc_fsync ((int (*) __P(( \
    520 		struct vnode *vp, \
    521 		int fflags, \
    522 		struct ucred *cred, \
    523 		int waitfor, \
    524 		struct proc *p))) nullop)
    525 #define fdesc_seek ((int (*) __P(( \
    526 		struct vnode *vp, \
    527 		off_t oldoff, \
    528 		off_t newoff, \
    529 		struct ucred *cred))) nullop)
    530 #define fdesc_remove ((int (*) __P(( \
    531 		struct nameidata *ndp, \
    532 		struct proc *p))) fdesc_enotsupp)
    533 #define fdesc_link ((int (*) __P(( \
    534 		struct vnode *vp, \
    535 		struct nameidata *ndp, \
    536 		struct proc *p))) fdesc_enotsupp)
    537 #define fdesc_rename ((int (*) __P(( \
    538 		struct nameidata *fndp, \
    539 		struct nameidata *tdnp, \
    540 		struct proc *p))) fdesc_enotsupp)
    541 #define fdesc_mkdir ((int (*) __P(( \
    542 		struct nameidata *ndp, \
    543 		struct vattr *vap, \
    544 		struct proc *p))) fdesc_enotsupp)
    545 #define fdesc_rmdir ((int (*) __P(( \
    546 		struct nameidata *ndp, \
    547 		struct proc *p))) fdesc_enotsupp)
    548 #define fdesc_symlink ((int (*) __P(( \
    549 		struct nameidata *ndp, \
    550 		struct vattr *vap, \
    551 		char *target, \
    552 		struct proc *p))) fdesc_enotsupp)
    553 #define fdesc_readlink ((int (*) __P(( \
    554 		struct vnode *vp, \
    555 		struct uio *uio, \
    556 		struct ucred *cred))) fdesc_enotsupp)
    557 #define fdesc_abortop ((int (*) __P(( \
    558 		struct nameidata *ndp))) nullop)
    559 #ifdef FDESC_DIAGNOSTIC
    560 int fdesc_reclaim(vp)
    561 struct vnode *vp;
    562 {
    563 	printf("fdesc_reclaim(%x)\n", vp);
    564 	return (0);
    565 }
    566 #else
    567 #define fdesc_reclaim ((int (*) __P(( \
    568 		struct vnode *vp))) nullop)
    569 #endif
    570 #define	fdesc_lock ((int (*) __P(( \
    571 		struct vnode *vp))) nullop)
    572 #define fdesc_unlock ((int (*) __P(( \
    573 		struct vnode *vp))) nullop)
    574 #define	fdesc_bmap ((int (*) __P(( \
    575 		struct vnode *vp, \
    576 		daddr_t bn, \
    577 		struct vnode **vpp, \
    578 		daddr_t *bnp))) fdesc_badop)
    579 #define	fdesc_strategy ((int (*) __P(( \
    580 		struct buf *bp))) fdesc_badop)
    581 #define fdesc_islocked ((int (*) __P(( \
    582 		struct vnode *vp))) nullop)
    583 #define fdesc_advlock ((int (*) __P(( \
    584 		struct vnode *vp, \
    585 		caddr_t id, \
    586 		int op, \
    587 		struct flock *fl, \
    588 		int flags))) fdesc_enotsupp)
    589 
    590 struct vnodeops fdesc_vnodeops = {
    591 	fdesc_lookup,	/* lookup */
    592 	fdesc_create,	/* create */
    593 	fdesc_mknod,	/* mknod */
    594 	fdesc_open,	/* open */
    595 	fdesc_close,	/* close */
    596 	fdesc_access,	/* access */
    597 	fdesc_getattr,	/* getattr */
    598 	fdesc_setattr,	/* setattr */
    599 	fdesc_read,	/* read */
    600 	fdesc_write,	/* write */
    601 	fdesc_ioctl,	/* ioctl */
    602 	fdesc_select,	/* select */
    603 	fdesc_mmap,	/* mmap */
    604 	fdesc_fsync,	/* fsync */
    605 	fdesc_seek,	/* seek */
    606 	fdesc_remove,	/* remove */
    607 	fdesc_link,	/* link */
    608 	fdesc_rename,	/* rename */
    609 	fdesc_mkdir,	/* mkdir */
    610 	fdesc_rmdir,	/* rmdir */
    611 	fdesc_symlink,	/* symlink */
    612 	fdesc_readdir,	/* readdir */
    613 	fdesc_readlink,	/* readlink */
    614 	fdesc_abortop,	/* abortop */
    615 	fdesc_inactive,	/* inactive */
    616 	fdesc_reclaim,	/* reclaim */
    617 	fdesc_lock,	/* lock */
    618 	fdesc_unlock,	/* unlock */
    619 	fdesc_bmap,	/* bmap */
    620 	fdesc_strategy,	/* strategy */
    621 	fdesc_print,	/* print */
    622 	fdesc_islocked,	/* islocked */
    623 	fdesc_advlock,	/* advlock */
    624 };
    625