xref: /original-bsd/sys/miscfs/fdesc/fdesc_vnops.c (revision 68d9582f)
1 /*
2  * Copyright (c) 1992 The Regents of the University of California
3  * Copyright (c) 1990, 1992 Jan-Simon Pendry
4  * All rights reserved.
5  *
6  * This code is derived from software donated to Berkeley by
7  * Jan-Simon Pendry.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)fdesc_vnops.c	1.2 (Berkeley) 06/18/92
12  *
13  * $Id: fdesc_vnops.c,v 1.7 1992/05/30 10:05:34 jsp Exp jsp $
14  */
15 
16 /*
17  * /dev/fd Filesystem
18  */
19 
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/types.h>
23 #include <sys/time.h>
24 #include <sys/proc.h>
25 #include <sys/resourcevar.h>
26 #include <sys/filedesc.h>
27 #include <sys/vnode.h>
28 #include <sys/malloc.h>
29 #include <sys/file.h>
30 #include <sys/stat.h>
31 #include <sys/mount.h>
32 #include <sys/namei.h>
33 #include <sys/buf.h>
34 #include <fdesc/fdesc.h>
35 
36 /*
37  * vp is the current namei directory
38  * ndp is the name to locate in that directory...
39  */
40 fdesc_lookup (ap)
41 	struct vop_lookup_args *ap;
42 {
43 	/*USES_VOP_LOCK;*/
44 	struct vnode **vpp = ap->a_vpp;
45 	struct vnode *dvp = ap->a_dvp;
46 	char *pname;
47 	struct proc *p;
48 	int nfiles;
49 	unsigned fd;
50 	int error;
51 	struct vnode *fvp;
52 
53 #ifdef FDESC_DIAGNOSTIC
54 	printf("fdesc_lookup(%x)\n", ap);
55 	printf("fdesc_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp);
56 #endif
57 	pname = ap->a_cnp->cn_nameptr;
58 #ifdef FDESC_DIAGNOSTIC
59 	printf("fdesc_lookup(%s)\n", pname);
60 #endif
61 	if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
62 		*vpp = dvp;
63 		VREF(dvp);
64 		/*VOP_LOCK(dvp);*/
65 		return (0);
66 	}
67 
68 	p = ap->a_cnp->cn_proc;
69 	nfiles = p->p_fd->fd_nfiles;
70 
71 	fd = 0;
72 	while (*pname >= '0' && *pname <= '9') {
73 		fd = 10 * fd + *pname++ - '0';
74 		if (fd >= nfiles)
75 			break;
76 	}
77 
78 #ifdef FDESC_DIAGNOSTIC
79 	printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname);
80 #endif
81 	if (*pname != '\0') {
82 		error = ENOENT;
83 		goto bad;
84 	}
85 
86 	if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) {
87 		error = EBADF;
88 		goto bad;
89 	}
90 
91 #ifdef FDESC_DIAGNOSTIC
92 	printf("fdesc_lookup: allocate new vnode\n");
93 #endif
94 	error = getnewvnode(VT_UFS, dvp->v_mount, fdesc_vnodeop_p, &fvp);
95 	if (error)
96 		goto bad;
97 	MALLOC(fvp->v_data, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK);
98 	VTOFDESC(fvp)->f_fd = fd;
99 	/*VTOFDESC(fvp)->f_isroot = 0;*/
100 	*vpp = fvp;
101 #ifdef FDESC_DIAGNOSTIC
102 	printf("fdesc_lookup: newvp = %x\n", fvp);
103 #endif
104 	return (0);
105 
106 bad:;
107 	*vpp = NULL;
108 #ifdef FDESC_DIAGNOSTIC
109 	printf("fdesc_lookup: error = %d\n", error);
110 #endif
111 	return (error);
112 }
113 
114 fdesc_open (ap)
115 	struct vop_open_args *ap;
116 {
117 	struct vnode *vp = ap->a_vp;
118 
119 	/*
120 	 * Can always open the root (modulo perms)
121 	 */
122 	if (vp->v_flag & VROOT)
123 		return (0);
124 
125 	/*
126 	 * XXX Kludge: set ap->a_p->p_dupfd to contain the value of the
127 	 * the file descriptor being sought for duplication. The error
128 	 * return ensures that the vnode for this device will be released
129 	 * by vn_open. Open will detect this special error and take the
130 	 * actions in dupfdopen.  Other callers of vn_open or VOP_OPEN
131 	 * will simply report the error.
132 	 */
133 	ap->a_p->p_dupfd = VTOFDESC(vp)->f_fd;	/* XXX */
134 	return (ENODEV);
135 }
136 
137 static int
138 fdesc_attr(fd, vap, cred, p)
139 	int fd;
140 	struct vattr *vap;
141 	struct ucred *cred;
142 	struct proc *p;
143 {
144 	USES_VOP_GETATTR;
145 	struct filedesc *fdp = p->p_fd;
146 	struct file *fp;
147 	int error;
148 
149 #ifdef FDESC_DIAGNOSTIC
150 	printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles);
151 #endif
152 	if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
153 #ifdef FDESC_DIAGNOSTIC
154 		printf("fdesc_attr: fp = %x (EBADF)\n", fp);
155 #endif
156 		return (EBADF);
157 	}
158 
159 	/*
160 	 * Can stat the underlying vnode, but not sockets because
161 	 * they don't use struct vattrs.  Well, we could convert from
162 	 * a struct stat back to a struct vattr, later...
163 	 */
164 	switch (fp->f_type) {
165 	case DTYPE_VNODE:
166 		error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
167 		break;
168 
169 	case DTYPE_SOCKET:
170 		error = EOPNOTSUPP;
171 		break;
172 
173 	default:
174 		panic("fdesc attr");
175 		break;
176 	}
177 
178 #ifdef FDESC_DIAGNOSTIC
179 	printf("fdesc_attr: returns error %d\n", error);
180 #endif
181 	return (error);
182 }
183 
184 fdesc_getattr (ap)
185 	struct vop_getattr_args *ap;
186 {
187 	struct vnode *vp = ap->a_vp;
188 	struct vattr *vap = ap->a_vap;
189 	unsigned fd;
190 	int error;
191 
192 	if (vp->v_flag & VROOT) {
193 #ifdef FDESC_DIAGNOSTIC
194 		printf("fdesc_getattr: stat rootdir\n");
195 #endif
196 		bzero((caddr_t) vap, sizeof(*vap));
197 		vattr_null(vap);
198 		vap->va_type = VDIR;
199 		vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
200 		vap->va_nlink = 2;
201 		vap->va_uid = 0;
202 		vap->va_gid = 0;
203 		vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
204 		vap->va_fileid = 2;
205 		/* vap->va_qsize = 0; */
206 		vap->va_size = DEV_BSIZE;
207 		vap->va_blocksize = DEV_BSIZE;
208 		microtime(&vap->va_atime);
209 		vap->va_mtime = vap->va_atime;
210 		vap->va_ctime = vap->va_ctime;
211 		vap->va_gen = 0;
212 		vap->va_flags = 0;
213 		vap->va_rdev = 0;
214 		/* vap->va_qbytes = 0; */
215 		vap->va_bytes = 0;
216 		return (0);
217 	}
218 
219 	fd = VTOFDESC(vp)->f_fd;
220 	error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p);
221 	if (error == 0)
222 		vp->v_type = vap->va_type;
223 	return (error);
224 }
225 
226 fdesc_setattr (ap)
227 	struct vop_setattr_args *ap;
228 {
229 	USES_VOP_SETATTR;
230 	struct filedesc *fdp = ap->a_p->p_fd;
231 	struct file *fp;
232 	unsigned fd;
233 	int error;
234 
235 	/*
236 	 * Can't mess with the root vnode
237 	 */
238 	if (ap->a_vp->v_flag & VROOT)
239 		return (EACCES);
240 
241 	fd = VTOFDESC(ap->a_vp)->f_fd;
242 #ifdef FDESC_DIAGNOSTIC
243 	printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles);
244 #endif
245 	if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
246 #ifdef FDESC_DIAGNOSTIC
247 		printf("fdesc_setattr: fp = %x (EBADF)\n", fp);
248 #endif
249 		return (EBADF);
250 	}
251 
252 	/*
253 	 * Can setattr the underlying vnode, but not sockets!
254 	 */
255 	switch (fp->f_type) {
256 	case DTYPE_VNODE:
257 		error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p);
258 		break;
259 
260 	case DTYPE_SOCKET:
261 		error = EOPNOTSUPP;
262 		break;
263 
264 	default:
265 		panic("fdesc setattr");
266 		break;
267 	}
268 
269 #ifdef FDESC_DIAGNOSTIC
270 	printf("fdesc_setattr: returns error %d\n", error);
271 #endif
272 	return (error);
273 }
274 
275 fdesc_readdir (ap)
276 	struct vop_readdir_args *ap;
277 {
278 	struct uio *uio = ap->a_uio;
279 	struct filedesc *fdp;
280 	int i;
281 	int error;
282 
283 #define UIO_MX 16
284 
285 	fdp = uio->uio_procp->p_fd;
286 	i = uio->uio_offset / UIO_MX;
287 	error = 0;
288 	while (uio->uio_resid > 0) {
289 		if (i >= fdp->fd_nfiles) {
290 			*ap->a_eofflagp = 1;
291 			break;
292 		}
293 		if (fdp->fd_ofiles[i] != NULL) {
294 			struct readdir d;
295 			struct readdir *dp = &d;
296 			char *cp = dp->d_name;
297 #ifdef FDESC_FILEID
298 			struct vattr va;
299 #endif
300 			bzero((caddr_t) dp, UIO_MX);
301 
302 			dp->d_namlen = sprintf(dp->d_name, "%d", i);
303 			/*
304 			 * Fill in the remaining fields
305 			 */
306 			dp->d_reclen = UIO_MX;
307 			dp->d_ino = i + 3;
308 #ifdef FDESC_FILEID
309 			/*
310 			 * If we want the file ids to match the
311 			 * we must call getattr on the underlying file.
312 			 * fdesc_attr may return an error, in which case
313 			 * we ignore the returned file id.
314 			 */
315 			error = fdesc_attr(i, &va, ap->a_cred, p);
316 			if (error == 0)
317 				dp->d_ino = va.va_fileid;
318 #endif
319 			/*
320 			 * And ship to userland
321 			 */
322 			error = uiomove((caddr_t) dp, UIO_MX, uio);
323 			if (error)
324 				break;
325 		}
326 		i++;
327 	}
328 
329 	uio->uio_offset = i * UIO_MX;
330 	return (error);
331 }
332 
333 fdesc_inactive (ap)
334 	struct vop_inactive_args *ap;
335 {
336 	struct vnode *vp = ap->a_vp;
337 
338 	/*
339 	 * Clear out the v_type field to avoid
340 	 * nasty things happening in vgone().
341 	 */
342 	vp->v_type = VNON;
343 #ifdef FDESC_DIAGNOSTIC
344 	printf("fdesc_inactive(%x)\n", vp);
345 #endif
346 	return (0);
347 }
348 
349 fdesc_reclaim (ap)
350 	struct  vop_reclaim_args *ap;
351 {
352 	struct vnode *vp = ap->a_vp;
353 	printf("fdesc_reclaim(%x)\n", vp);
354 	if (vp->v_data) {
355 		FREE(vp->v_data, M_TEMP);
356 		vp->v_data = 0;
357 	}
358 	return (0);
359 }
360 
361 /*
362  * Print out the contents of a /dev/fd vnode.
363  */
364 /* ARGSUSED */
365 fdesc_print (ap)
366 	struct vop_print_args *ap;
367 {
368 	printf("tag VT_NON, fdesc vnode\n");
369 }
370 
371 /*void*/
372 fdesc_vfree (ap)
373 	struct vop_vfree_args *ap;
374 {
375 
376 	return;
377 }
378 
379 /*
380  * /dev/fd vnode unsupported operation
381  */
382 fdesc_enotsupp()
383 {
384 	return (EOPNOTSUPP);
385 }
386 
387 /*
388  * /dev/fd "should never get here" operation
389  */
390 fdesc_badop()
391 {
392 	panic("fdesc: bad op");
393 	/* NOTREACHED */
394 }
395 
396 /*
397  * /dev/fd vnode null operation
398  */
399 fdesc_nullop()
400 {
401 	return (0);
402 }
403 
404 #define fdesc_create ((int (*) __P((struct  vop_create_args *)))fdesc_enotsupp)
405 #define fdesc_mknod ((int (*) __P((struct  vop_mknod_args *)))fdesc_enotsupp)
406 #define fdesc_close ((int (*) __P((struct  vop_close_args *)))nullop)
407 #define fdesc_access ((int (*) __P((struct  vop_access_args *)))nullop)
408 #define fdesc_read ((int (*) __P((struct  vop_read_args *)))fdesc_enotsupp)
409 #define fdesc_write ((int (*) __P((struct  vop_write_args *)))fdesc_enotsupp)
410 #define fdesc_ioctl ((int (*) __P((struct  vop_ioctl_args *)))fdesc_enotsupp)
411 #define fdesc_select ((int (*) __P((struct  vop_select_args *)))fdesc_enotsupp)
412 #define fdesc_mmap ((int (*) __P((struct  vop_mmap_args *)))fdesc_enotsupp)
413 #define fdesc_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
414 #define fdesc_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
415 #define fdesc_remove ((int (*) __P((struct  vop_remove_args *)))fdesc_enotsupp)
416 #define fdesc_link ((int (*) __P((struct  vop_link_args *)))fdesc_enotsupp)
417 #define fdesc_rename ((int (*) __P((struct  vop_rename_args *)))fdesc_enotsupp)
418 #define fdesc_mkdir ((int (*) __P((struct  vop_mkdir_args *)))fdesc_enotsupp)
419 #define fdesc_rmdir ((int (*) __P((struct  vop_rmdir_args *)))fdesc_enotsupp)
420 #define fdesc_symlink ((int (*) __P((struct  vop_symlink_args *)))fdesc_enotsupp)
421 #define fdesc_readlink ((int (*) __P((struct  vop_readlink_args *)))fdesc_enotsupp)
422 #define fdesc_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
423 #define fdesc_lock ((int (*) __P((struct  vop_lock_args *)))nullop)
424 #define fdesc_unlock ((int (*) __P((struct  vop_unlock_args *)))nullop)
425 #define fdesc_bmap ((int (*) __P((struct  vop_bmap_args *)))fdesc_badop)
426 #define fdesc_strategy ((int (*) __P((struct  vop_strategy_args *)))fdesc_badop)
427 #define fdesc_islocked ((int (*) __P((struct  vop_islocked_args *)))nullop)
428 #define fdesc_advlock ((int (*) __P((struct  vop_advlock_args *)))fdesc_enotsupp)
429 #define fdesc_blkatoff ((int (*) __P((struct  vop_blkatoff_args *)))fdesc_enotsupp)
430 #define fdesc_vget ((int (*) __P((struct  vop_vget_args *)))fdesc_enotsupp)
431 #define fdesc_valloc ((int(*) __P(( \
432 		struct vnode *pvp, \
433 		int mode, \
434 		struct ucred *cred, \
435 		struct vnode **vpp))) fdesc_enotsupp)
436 #define fdesc_truncate ((int (*) __P((struct  vop_truncate_args *)))fdesc_enotsupp)
437 #define fdesc_update ((int (*) __P((struct  vop_update_args *)))fdesc_enotsupp)
438 #define fdesc_bwrite ((int (*) __P((struct  vop_bwrite_args *)))fdesc_enotsupp)
439 
440 int (**fdesc_vnodeop_p)();
441 struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
442 	{ &vop_default_desc, vn_default_error },
443 	{ &vop_lookup_desc, fdesc_lookup },	/* lookup */
444 	{ &vop_create_desc, fdesc_create },	/* create */
445 	{ &vop_mknod_desc, fdesc_mknod },	/* mknod */
446 	{ &vop_open_desc, fdesc_open },	/* open */
447 	{ &vop_close_desc, fdesc_close },	/* close */
448 	{ &vop_access_desc, fdesc_access },	/* access */
449 	{ &vop_getattr_desc, fdesc_getattr },	/* getattr */
450 	{ &vop_setattr_desc, fdesc_setattr },	/* setattr */
451 	{ &vop_read_desc, fdesc_read },	/* read */
452 	{ &vop_write_desc, fdesc_write },	/* write */
453 	{ &vop_ioctl_desc, fdesc_ioctl },	/* ioctl */
454 	{ &vop_select_desc, fdesc_select },	/* select */
455 	{ &vop_mmap_desc, fdesc_mmap },	/* mmap */
456 	{ &vop_fsync_desc, fdesc_fsync },	/* fsync */
457 	{ &vop_seek_desc, fdesc_seek },	/* seek */
458 	{ &vop_remove_desc, fdesc_remove },	/* remove */
459 	{ &vop_link_desc, fdesc_link },	/* link */
460 	{ &vop_rename_desc, fdesc_rename },	/* rename */
461 	{ &vop_mkdir_desc, fdesc_mkdir },	/* mkdir */
462 	{ &vop_rmdir_desc, fdesc_rmdir },	/* rmdir */
463 	{ &vop_symlink_desc, fdesc_symlink },	/* symlink */
464 	{ &vop_readdir_desc, fdesc_readdir },	/* readdir */
465 	{ &vop_readlink_desc, fdesc_readlink },	/* readlink */
466 	{ &vop_abortop_desc, fdesc_abortop },	/* abortop */
467 	{ &vop_inactive_desc, fdesc_inactive },	/* inactive */
468 	{ &vop_reclaim_desc, fdesc_reclaim },	/* reclaim */
469 	{ &vop_lock_desc, fdesc_lock },	/* lock */
470 	{ &vop_unlock_desc, fdesc_unlock },	/* unlock */
471 	{ &vop_bmap_desc, fdesc_bmap },	/* bmap */
472 	{ &vop_strategy_desc, fdesc_strategy },	/* strategy */
473 	{ &vop_print_desc, fdesc_print },	/* print */
474 	{ &vop_islocked_desc, fdesc_islocked },	/* islocked */
475 	{ &vop_advlock_desc, fdesc_advlock },	/* advlock */
476 	{ &vop_blkatoff_desc, fdesc_blkatoff },	/* blkatoff */
477 	{ &vop_vget_desc, fdesc_vget },	/* vget */
478 	{ &vop_valloc_desc, fdesc_valloc },	/* valloc */
479 	{ &vop_vfree_desc, fdesc_vfree },	/* vfree */
480 	{ &vop_truncate_desc, fdesc_truncate },	/* truncate */
481 	{ &vop_update_desc, fdesc_update },	/* update */
482 	{ &vop_bwrite_desc, fdesc_bwrite },	/* bwrite */
483 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
484 };
485 struct vnodeopv_desc fdesc_vnodeop_opv_desc =
486 	{ &fdesc_vnodeop_p, fdesc_vnodeop_entries };
487