Commit | Line | Data |
---|---|---|
e2e9adba | 1 | /* |
5f0f7060 KB |
2 | * Copyright (c) 1992, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
e2e9adba JSP |
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 | * | |
43ec9518 | 11 | * @(#)fdesc_vnops.c 8.7 (Berkeley) %G% |
e2e9adba | 12 | * |
01936f59 | 13 | * $Id: fdesc_vnops.c,v 1.12 1993/04/06 16:17:17 jsp Exp $ |
e2e9adba 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> | |
01936f59 | 25 | #include <sys/kernel.h> /* boottime */ |
e2e9adba JSP |
26 | #include <sys/resourcevar.h> |
27 | #include <sys/filedesc.h> | |
28 | #include <sys/vnode.h> | |
29 | #include <sys/malloc.h> | |
30 | #include <sys/file.h> | |
31 | #include <sys/stat.h> | |
32 | #include <sys/mount.h> | |
33 | #include <sys/namei.h> | |
34 | #include <sys/buf.h> | |
13ef814e | 35 | #include <sys/dirent.h> |
5e3f92c4 | 36 | #include <miscfs/fdesc/fdesc.h> |
e2e9adba | 37 | |
cf5ef508 | 38 | #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL) |
01936f59 JSP |
39 | |
40 | #define FDL_WANT 0x01 | |
41 | #define FDL_LOCKED 0x02 | |
43ec9518 JSP |
42 | static int fdcache_lock; |
43 | ||
44 | dev_t devctty; | |
01936f59 JSP |
45 | |
46 | #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) | |
47 | FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 | |
48 | #endif | |
49 | ||
43ec9518 JSP |
50 | #define NFDCACHE 3 |
51 | #define FD_NHASH(ix) ((ix) & NFDCACHE) | |
52 | ||
53 | /* | |
54 | * Cache head | |
55 | */ | |
56 | struct fdcache { | |
57 | struct fdescnode *fc_forw; | |
58 | struct fdescnode *fc_back; | |
59 | }; | |
60 | ||
61 | static struct fdcache fdcache[NFDCACHE]; | |
62 | ||
63 | /* | |
64 | * Initialise cache headers | |
65 | */ | |
66 | fdesc_init() | |
67 | { | |
68 | struct fdcache *fc; | |
69 | ||
70 | devctty = makedev(nchrdev, 0); | |
71 | ||
72 | for (fc = fdcache; fc < fdcache + NFDCACHE; fc++) | |
73 | fc->fc_forw = fc->fc_back = (struct fdescnode *) fc; | |
74 | } | |
75 | ||
76 | /* | |
77 | * Compute hash list for given target vnode | |
78 | */ | |
79 | static struct fdcache * | |
80 | fdesc_hash(ix) | |
81 | int ix; | |
82 | { | |
83 | ||
84 | return (&fdcache[FD_NHASH(ix)]); | |
85 | } | |
86 | ||
87 | int | |
01936f59 JSP |
88 | fdesc_allocvp(ftype, ix, mp, vpp) |
89 | fdntype ftype; | |
90 | int ix; | |
91 | struct mount *mp; | |
92 | struct vnode **vpp; | |
93 | { | |
43ec9518 JSP |
94 | struct fdcache *fc; |
95 | struct fdescnode *fd; | |
01936f59 JSP |
96 | int error = 0; |
97 | ||
a6382592 | 98 | loop: |
43ec9518 JSP |
99 | fc = fdesc_hash(ix); |
100 | for (fd = fc->fc_forw; fd != (struct fdescnode *) fc; fd = fd->fd_forw) { | |
101 | if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { | |
102 | if (vget(fd->fd_vnode, 0)) | |
a6382592 | 103 | goto loop; |
43ec9518 | 104 | *vpp = fd->fd_vnode; |
01936f59 JSP |
105 | return (error); |
106 | } | |
107 | } | |
108 | ||
109 | /* | |
110 | * otherwise lock the array while we call getnewvnode | |
111 | * since that can block. | |
112 | */ | |
43ec9518 JSP |
113 | if (fdcache_lock & FDL_LOCKED) { |
114 | fdcache_lock |= FDL_WANT; | |
115 | sleep((caddr_t) &fdcache_lock, PINOD); | |
a6382592 | 116 | goto loop; |
01936f59 | 117 | } |
43ec9518 | 118 | fdcache_lock |= FDL_LOCKED; |
01936f59 | 119 | |
46a14367 | 120 | error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp); |
01936f59 JSP |
121 | if (error) |
122 | goto out; | |
43ec9518 JSP |
123 | MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); |
124 | (*vpp)->v_data = fd; | |
125 | fd->fd_vnode = *vpp; | |
126 | fd->fd_type = ftype; | |
127 | fd->fd_fd = -1; | |
128 | fd->fd_link = 0; | |
129 | fd->fd_ix = ix; | |
130 | fc = fdesc_hash(ix); | |
131 | insque(fd, fc); | |
01936f59 JSP |
132 | |
133 | out:; | |
43ec9518 | 134 | fdcache_lock &= ~FDL_LOCKED; |
01936f59 | 135 | |
43ec9518 JSP |
136 | if (fdcache_lock & FDL_WANT) { |
137 | fdcache_lock &= ~FDL_WANT; | |
138 | wakeup((caddr_t) &fdcache_lock); | |
01936f59 JSP |
139 | } |
140 | ||
141 | return (error); | |
142 | } | |
143 | ||
e2e9adba JSP |
144 | /* |
145 | * vp is the current namei directory | |
146 | * ndp is the name to locate in that directory... | |
147 | */ | |
43ec9518 | 148 | int |
5e3f92c4 KM |
149 | fdesc_lookup(ap) |
150 | struct vop_lookup_args /* { | |
151 | struct vnode * a_dvp; | |
152 | struct vnode ** a_vpp; | |
153 | struct componentname * a_cnp; | |
154 | } */ *ap; | |
e2e9adba | 155 | { |
a02db9dd JSP |
156 | struct vnode **vpp = ap->a_vpp; |
157 | struct vnode *dvp = ap->a_dvp; | |
e2e9adba JSP |
158 | char *pname; |
159 | struct proc *p; | |
160 | int nfiles; | |
161 | unsigned fd; | |
162 | int error; | |
163 | struct vnode *fvp; | |
01936f59 | 164 | char *ln; |
e2e9adba | 165 | |
e2e9adba | 166 | pname = ap->a_cnp->cn_nameptr; |
e2e9adba | 167 | if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { |
a02db9dd JSP |
168 | *vpp = dvp; |
169 | VREF(dvp); | |
01936f59 | 170 | VOP_LOCK(dvp); |
e2e9adba JSP |
171 | return (0); |
172 | } | |
173 | ||
174 | p = ap->a_cnp->cn_proc; | |
175 | nfiles = p->p_fd->fd_nfiles; | |
176 | ||
01936f59 JSP |
177 | switch (VTOFDESC(dvp)->fd_type) { |
178 | default: | |
179 | case Flink: | |
180 | case Fdesc: | |
181 | case Fctty: | |
182 | error = ENOTDIR; | |
183 | goto bad; | |
184 | ||
185 | case Froot: | |
186 | if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) { | |
187 | error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); | |
188 | if (error) | |
189 | goto bad; | |
190 | *vpp = fvp; | |
191 | fvp->v_type = VDIR; | |
192 | VOP_LOCK(fvp); | |
01936f59 JSP |
193 | return (0); |
194 | } | |
195 | ||
196 | if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) { | |
197 | struct vnode *ttyvp = cttyvp(p); | |
198 | if (ttyvp == NULL) { | |
199 | error = ENXIO; | |
200 | goto bad; | |
201 | } | |
202 | error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); | |
203 | if (error) | |
204 | goto bad; | |
205 | *vpp = fvp; | |
206 | fvp->v_type = VFIFO; | |
207 | VOP_LOCK(fvp); | |
01936f59 JSP |
208 | return (0); |
209 | } | |
210 | ||
211 | ln = 0; | |
212 | switch (ap->a_cnp->cn_namelen) { | |
213 | case 5: | |
214 | if (bcmp(pname, "stdin", 5) == 0) { | |
215 | ln = "fd/0"; | |
216 | fd = FD_STDIN; | |
217 | } | |
e2e9adba | 218 | break; |
01936f59 JSP |
219 | case 6: |
220 | if (bcmp(pname, "stdout", 6) == 0) { | |
221 | ln = "fd/1"; | |
222 | fd = FD_STDOUT; | |
223 | } else | |
224 | if (bcmp(pname, "stderr", 6) == 0) { | |
225 | ln = "fd/2"; | |
226 | fd = FD_STDERR; | |
227 | } | |
228 | break; | |
229 | } | |
e2e9adba | 230 | |
01936f59 | 231 | if (ln) { |
01936f59 JSP |
232 | error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); |
233 | if (error) | |
234 | goto bad; | |
235 | VTOFDESC(fvp)->fd_link = ln; | |
236 | *vpp = fvp; | |
237 | fvp->v_type = VLNK; | |
238 | VOP_LOCK(fvp); | |
01936f59 JSP |
239 | return (0); |
240 | } else { | |
241 | error = ENOENT; | |
242 | goto bad; | |
243 | } | |
e2e9adba | 244 | |
43ec9518 | 245 | /* FALL THROUGH */ |
01936f59 JSP |
246 | |
247 | case Fdevfd: | |
248 | if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) { | |
249 | error = fdesc_root(dvp->v_mount, vpp); | |
250 | return (error); | |
251 | } | |
252 | ||
253 | fd = 0; | |
254 | while (*pname >= '0' && *pname <= '9') { | |
255 | fd = 10 * fd + *pname++ - '0'; | |
256 | if (fd >= nfiles) | |
257 | break; | |
258 | } | |
e2e9adba | 259 | |
01936f59 JSP |
260 | if (*pname != '\0') { |
261 | error = ENOENT; | |
262 | goto bad; | |
263 | } | |
264 | ||
265 | if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { | |
266 | error = EBADF; | |
267 | goto bad; | |
268 | } | |
269 | ||
01936f59 JSP |
270 | error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); |
271 | if (error) | |
272 | goto bad; | |
273 | VTOFDESC(fvp)->fd_fd = fd; | |
274 | *vpp = fvp; | |
01936f59 JSP |
275 | return (0); |
276 | } | |
e2e9adba JSP |
277 | |
278 | bad:; | |
a02db9dd | 279 | *vpp = NULL; |
e2e9adba JSP |
280 | return (error); |
281 | } | |
282 | ||
43ec9518 | 283 | int |
5e3f92c4 KM |
284 | fdesc_open(ap) |
285 | struct vop_open_args /* { | |
286 | struct vnode *a_vp; | |
287 | int a_mode; | |
288 | struct ucred *a_cred; | |
289 | struct proc *a_p; | |
290 | } */ *ap; | |
e2e9adba | 291 | { |
a02db9dd | 292 | struct vnode *vp = ap->a_vp; |
01936f59 JSP |
293 | int error = 0; |
294 | ||
295 | switch (VTOFDESC(vp)->fd_type) { | |
296 | case Fdesc: | |
297 | /* | |
298 | * XXX Kludge: set p->p_dupfd to contain the value of the | |
299 | * the file descriptor being sought for duplication. The error | |
300 | * return ensures that the vnode for this device will be | |
301 | * released by vn_open. Open will detect this special error and | |
302 | * take the actions in dupfdopen. Other callers of vn_open or | |
303 | * VOP_OPEN will simply report the error. | |
304 | */ | |
305 | ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ | |
306 | error = ENODEV; | |
307 | break; | |
a02db9dd | 308 | |
01936f59 JSP |
309 | case Fctty: |
310 | error = cttyopen(devctty, ap->a_mode, 0, ap->a_p); | |
311 | break; | |
312 | } | |
e2e9adba | 313 | |
01936f59 | 314 | return (error); |
e2e9adba JSP |
315 | } |
316 | ||
317 | static int | |
318 | fdesc_attr(fd, vap, cred, p) | |
319 | int fd; | |
320 | struct vattr *vap; | |
321 | struct ucred *cred; | |
322 | struct proc *p; | |
323 | { | |
e2e9adba JSP |
324 | struct filedesc *fdp = p->p_fd; |
325 | struct file *fp; | |
7e204c1b | 326 | struct stat stb; |
e2e9adba JSP |
327 | int error; |
328 | ||
43ec9518 | 329 | if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) |
e2e9adba | 330 | return (EBADF); |
e2e9adba | 331 | |
e2e9adba JSP |
332 | switch (fp->f_type) { |
333 | case DTYPE_VNODE: | |
334 | error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); | |
52e93dd0 JSP |
335 | if (error == 0 && vap->va_type == VDIR) { |
336 | /* | |
337 | * don't allow directories to show up because | |
338 | * that causes loops in the namespace. | |
339 | */ | |
340 | vap->va_type = VFIFO; | |
341 | } | |
e2e9adba JSP |
342 | break; |
343 | ||
344 | case DTYPE_SOCKET: | |
7e204c1b JSP |
345 | error = soo_stat((struct socket *)fp->f_data, &stb); |
346 | if (error == 0) { | |
347 | vattr_null(vap); | |
348 | vap->va_type = VSOCK; | |
349 | vap->va_mode = stb.st_mode; | |
350 | vap->va_nlink = stb.st_nlink; | |
351 | vap->va_uid = stb.st_uid; | |
352 | vap->va_gid = stb.st_gid; | |
353 | vap->va_fsid = stb.st_dev; | |
354 | vap->va_fileid = stb.st_ino; | |
355 | vap->va_size = stb.st_size; | |
356 | vap->va_blocksize = stb.st_blksize; | |
357 | vap->va_atime = stb.st_atimespec; | |
358 | vap->va_mtime = stb.st_mtimespec; | |
359 | vap->va_ctime = stb.st_ctimespec; | |
360 | vap->va_gen = stb.st_gen; | |
361 | vap->va_flags = stb.st_flags; | |
362 | vap->va_rdev = stb.st_rdev; | |
363 | vap->va_bytes = stb.st_blocks * stb.st_blksize; | |
364 | } | |
e2e9adba JSP |
365 | break; |
366 | ||
367 | default: | |
368 | panic("fdesc attr"); | |
369 | break; | |
370 | } | |
371 | ||
e2e9adba JSP |
372 | return (error); |
373 | } | |
374 | ||
43ec9518 | 375 | int |
5e3f92c4 KM |
376 | fdesc_getattr(ap) |
377 | struct vop_getattr_args /* { | |
378 | struct vnode *a_vp; | |
379 | struct vattr *a_vap; | |
380 | struct ucred *a_cred; | |
381 | struct proc *a_p; | |
382 | } */ *ap; | |
e2e9adba | 383 | { |
a02db9dd JSP |
384 | struct vnode *vp = ap->a_vp; |
385 | struct vattr *vap = ap->a_vap; | |
e2e9adba | 386 | unsigned fd; |
6a6b2974 | 387 | int error = 0; |
e2e9adba | 388 | |
01936f59 JSP |
389 | switch (VTOFDESC(vp)->fd_type) { |
390 | case Froot: | |
391 | case Fdevfd: | |
392 | case Flink: | |
393 | case Fctty: | |
a02db9dd JSP |
394 | bzero((caddr_t) vap, sizeof(*vap)); |
395 | vattr_null(vap); | |
01936f59 JSP |
396 | vap->va_fileid = VTOFDESC(vp)->fd_ix; |
397 | ||
398 | switch (VTOFDESC(vp)->fd_type) { | |
399 | case Flink: | |
400 | vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; | |
401 | vap->va_type = VLNK; | |
402 | vap->va_nlink = 1; | |
01936f59 JSP |
403 | vap->va_size = strlen(VTOFDESC(vp)->fd_link); |
404 | break; | |
405 | ||
406 | case Fctty: | |
407 | vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; | |
408 | vap->va_type = VFIFO; | |
409 | vap->va_nlink = 1; | |
01936f59 JSP |
410 | vap->va_size = 0; |
411 | break; | |
412 | ||
413 | default: | |
414 | vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; | |
415 | vap->va_type = VDIR; | |
416 | vap->va_nlink = 2; | |
01936f59 JSP |
417 | vap->va_size = DEV_BSIZE; |
418 | break; | |
419 | } | |
a02db9dd JSP |
420 | vap->va_uid = 0; |
421 | vap->va_gid = 0; | |
422 | vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; | |
a02db9dd | 423 | vap->va_blocksize = DEV_BSIZE; |
01936f59 JSP |
424 | vap->va_atime.ts_sec = boottime.tv_sec; |
425 | vap->va_atime.ts_nsec = 0; | |
a02db9dd | 426 | vap->va_mtime = vap->va_atime; |
ede11b31 | 427 | vap->va_ctime = vap->va_mtime; |
a02db9dd JSP |
428 | vap->va_gen = 0; |
429 | vap->va_flags = 0; | |
430 | vap->va_rdev = 0; | |
a02db9dd | 431 | vap->va_bytes = 0; |
01936f59 JSP |
432 | break; |
433 | ||
434 | case Fdesc: | |
01936f59 JSP |
435 | fd = VTOFDESC(vp)->fd_fd; |
436 | error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); | |
437 | break; | |
438 | ||
439 | default: | |
440 | panic("fdesc_getattr"); | |
441 | break; | |
e2e9adba JSP |
442 | } |
443 | ||
e2e9adba | 444 | if (error == 0) |
a02db9dd | 445 | vp->v_type = vap->va_type; |
01936f59 | 446 | |
e2e9adba JSP |
447 | return (error); |
448 | } | |
449 | ||
43ec9518 | 450 | int |
5e3f92c4 KM |
451 | fdesc_setattr(ap) |
452 | struct vop_setattr_args /* { | |
453 | struct vnode *a_vp; | |
454 | struct vattr *a_vap; | |
455 | struct ucred *a_cred; | |
456 | struct proc *a_p; | |
457 | } */ *ap; | |
e2e9adba | 458 | { |
e2e9adba JSP |
459 | struct filedesc *fdp = ap->a_p->p_fd; |
460 | struct file *fp; | |
461 | unsigned fd; | |
462 | int error; | |
463 | ||
464 | /* | |
465 | * Can't mess with the root vnode | |
466 | */ | |
01936f59 JSP |
467 | switch (VTOFDESC(ap->a_vp)->fd_type) { |
468 | case Fdesc: | |
469 | break; | |
470 | ||
471 | case Fctty: | |
472 | return (0); | |
473 | ||
474 | default: | |
e2e9adba | 475 | return (EACCES); |
01936f59 | 476 | } |
e2e9adba | 477 | |
01936f59 | 478 | fd = VTOFDESC(ap->a_vp)->fd_fd; |
e2e9adba | 479 | if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { |
e2e9adba JSP |
480 | return (EBADF); |
481 | } | |
482 | ||
483 | /* | |
484 | * Can setattr the underlying vnode, but not sockets! | |
485 | */ | |
486 | switch (fp->f_type) { | |
487 | case DTYPE_VNODE: | |
488 | error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p); | |
489 | break; | |
490 | ||
491 | case DTYPE_SOCKET: | |
d5ef2099 | 492 | error = 0; |
e2e9adba JSP |
493 | break; |
494 | ||
495 | default: | |
496 | panic("fdesc setattr"); | |
497 | break; | |
498 | } | |
499 | ||
e2e9adba JSP |
500 | return (error); |
501 | } | |
502 | ||
01936f59 JSP |
503 | #define UIO_MX 16 |
504 | ||
505 | static struct dirtmp { | |
506 | u_long d_fileno; | |
507 | u_short d_reclen; | |
508 | u_short d_namlen; | |
509 | char d_name[8]; | |
510 | } rootent[] = { | |
511 | { FD_DEVFD, UIO_MX, 2, "fd" }, | |
512 | { FD_STDIN, UIO_MX, 5, "stdin" }, | |
513 | { FD_STDOUT, UIO_MX, 6, "stdout" }, | |
514 | { FD_STDERR, UIO_MX, 6, "stderr" }, | |
515 | { FD_CTTY, UIO_MX, 3, "tty" }, | |
516 | { 0 } | |
517 | }; | |
518 | ||
43ec9518 | 519 | int |
5e3f92c4 KM |
520 | fdesc_readdir(ap) |
521 | struct vop_readdir_args /* { | |
522 | struct vnode *a_vp; | |
523 | struct uio *a_uio; | |
524 | struct ucred *a_cred; | |
525 | } */ *ap; | |
e2e9adba | 526 | { |
a02db9dd | 527 | struct uio *uio = ap->a_uio; |
e2e9adba JSP |
528 | struct filedesc *fdp; |
529 | int i; | |
530 | int error; | |
531 | ||
01936f59 JSP |
532 | switch (VTOFDESC(ap->a_vp)->fd_type) { |
533 | case Fctty: | |
534 | return (0); | |
535 | ||
536 | case Fdesc: | |
537 | return (ENOTDIR); | |
538 | ||
539 | default: | |
540 | break; | |
541 | } | |
e2e9adba | 542 | |
a02db9dd | 543 | fdp = uio->uio_procp->p_fd; |
01936f59 JSP |
544 | |
545 | if (VTOFDESC(ap->a_vp)->fd_type == Froot) { | |
546 | struct dirent d; | |
547 | struct dirent *dp = &d; | |
548 | struct dirtmp *dt; | |
549 | ||
550 | i = uio->uio_offset / UIO_MX; | |
551 | error = 0; | |
552 | ||
553 | while (uio->uio_resid > 0) { | |
554 | dt = &rootent[i]; | |
555 | if (dt->d_fileno == 0) { | |
556 | /**eofflagp = 1;*/ | |
557 | break; | |
558 | } | |
559 | i++; | |
560 | ||
561 | switch (dt->d_fileno) { | |
562 | case FD_CTTY: | |
563 | if (cttyvp(uio->uio_procp) == NULL) | |
564 | continue; | |
565 | break; | |
566 | ||
567 | case FD_STDIN: | |
568 | case FD_STDOUT: | |
569 | case FD_STDERR: | |
ede11b31 | 570 | if ((dt->d_fileno-FD_STDIN) >= fdp->fd_nfiles) |
01936f59 | 571 | continue; |
ede11b31 | 572 | if (fdp->fd_ofiles[dt->d_fileno-FD_STDIN] == NULL) |
01936f59 JSP |
573 | continue; |
574 | break; | |
575 | } | |
ede11b31 | 576 | bzero((caddr_t) dp, UIO_MX); |
01936f59 JSP |
577 | dp->d_fileno = dt->d_fileno; |
578 | dp->d_namlen = dt->d_namlen; | |
579 | dp->d_type = DT_UNKNOWN; | |
580 | dp->d_reclen = dt->d_reclen; | |
581 | bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); | |
582 | error = uiomove((caddr_t) dp, UIO_MX, uio); | |
583 | if (error) | |
584 | break; | |
585 | } | |
586 | uio->uio_offset = i * UIO_MX; | |
587 | return (error); | |
588 | } | |
589 | ||
a02db9dd | 590 | i = uio->uio_offset / UIO_MX; |
e2e9adba | 591 | error = 0; |
a02db9dd | 592 | while (uio->uio_resid > 0) { |
43ec9518 | 593 | if (i >= fdp->fd_nfiles) |
e2e9adba | 594 | break; |
43ec9518 | 595 | |
e2e9adba | 596 | if (fdp->fd_ofiles[i] != NULL) { |
13ef814e JSP |
597 | struct dirent d; |
598 | struct dirent *dp = &d; | |
43ec9518 | 599 | |
e2e9adba JSP |
600 | bzero((caddr_t) dp, UIO_MX); |
601 | ||
602 | dp->d_namlen = sprintf(dp->d_name, "%d", i); | |
e2e9adba | 603 | dp->d_reclen = UIO_MX; |
13ef814e | 604 | dp->d_type = DT_UNKNOWN; |
01936f59 | 605 | dp->d_fileno = i + FD_STDIN; |
e2e9adba JSP |
606 | /* |
607 | * And ship to userland | |
608 | */ | |
a02db9dd | 609 | error = uiomove((caddr_t) dp, UIO_MX, uio); |
e2e9adba JSP |
610 | if (error) |
611 | break; | |
612 | } | |
613 | i++; | |
614 | } | |
615 | ||
a02db9dd | 616 | uio->uio_offset = i * UIO_MX; |
e2e9adba JSP |
617 | return (error); |
618 | } | |
619 | ||
01936f59 JSP |
620 | int |
621 | fdesc_readlink(ap) | |
622 | struct vop_readlink_args /* { | |
623 | struct vnode *a_vp; | |
624 | struct uio *a_uio; | |
625 | struct ucred *a_cred; | |
626 | } */ *ap; | |
627 | { | |
43ec9518 | 628 | struct vnode *vp = ap->a_vp; |
01936f59 JSP |
629 | int error; |
630 | ||
631 | if (vp->v_type != VLNK) | |
632 | return (EPERM); | |
633 | ||
634 | if (VTOFDESC(vp)->fd_type == Flink) { | |
635 | char *ln = VTOFDESC(vp)->fd_link; | |
636 | error = uiomove(ln, strlen(ln), ap->a_uio); | |
637 | } else { | |
638 | error = EOPNOTSUPP; | |
639 | } | |
640 | ||
641 | return (error); | |
642 | } | |
643 | ||
43ec9518 | 644 | int |
01936f59 JSP |
645 | fdesc_read(ap) |
646 | struct vop_read_args /* { | |
647 | struct vnode *a_vp; | |
648 | struct uio *a_uio; | |
649 | int a_ioflag; | |
650 | struct ucred *a_cred; | |
651 | } */ *ap; | |
652 | { | |
653 | int error = EOPNOTSUPP; | |
654 | ||
655 | switch (VTOFDESC(ap->a_vp)->fd_type) { | |
656 | case Fctty: | |
657 | error = cttyread(devctty, ap->a_uio, ap->a_ioflag); | |
658 | break; | |
659 | ||
660 | default: | |
661 | error = EOPNOTSUPP; | |
662 | break; | |
663 | } | |
664 | ||
665 | return (error); | |
666 | } | |
667 | ||
43ec9518 | 668 | int |
01936f59 JSP |
669 | fdesc_write(ap) |
670 | struct vop_write_args /* { | |
671 | struct vnode *a_vp; | |
672 | struct uio *a_uio; | |
673 | int a_ioflag; | |
674 | struct ucred *a_cred; | |
675 | } */ *ap; | |
676 | { | |
677 | int error = EOPNOTSUPP; | |
678 | ||
679 | switch (VTOFDESC(ap->a_vp)->fd_type) { | |
680 | case Fctty: | |
681 | error = cttywrite(devctty, ap->a_uio, ap->a_ioflag); | |
682 | break; | |
683 | ||
684 | default: | |
685 | error = EOPNOTSUPP; | |
686 | break; | |
687 | } | |
688 | ||
689 | return (error); | |
690 | } | |
691 | ||
43ec9518 | 692 | int |
01936f59 JSP |
693 | fdesc_ioctl(ap) |
694 | struct vop_ioctl_args /* { | |
695 | struct vnode *a_vp; | |
696 | int a_command; | |
697 | caddr_t a_data; | |
698 | int a_fflag; | |
699 | struct ucred *a_cred; | |
700 | struct proc *a_p; | |
701 | } */ *ap; | |
702 | { | |
703 | int error = EOPNOTSUPP; | |
704 | ||
01936f59 JSP |
705 | switch (VTOFDESC(ap->a_vp)->fd_type) { |
706 | case Fctty: | |
707 | error = cttyioctl(devctty, ap->a_command, ap->a_data, | |
708 | ap->a_fflag, ap->a_p); | |
709 | break; | |
710 | ||
711 | default: | |
712 | error = EOPNOTSUPP; | |
713 | break; | |
714 | } | |
715 | ||
716 | return (error); | |
717 | } | |
718 | ||
43ec9518 | 719 | int |
01936f59 JSP |
720 | fdesc_select(ap) |
721 | struct vop_select_args /* { | |
722 | struct vnode *a_vp; | |
723 | int a_which; | |
724 | int a_fflags; | |
725 | struct ucred *a_cred; | |
726 | struct proc *a_p; | |
727 | } */ *ap; | |
728 | { | |
729 | int error = EOPNOTSUPP; | |
730 | ||
731 | switch (VTOFDESC(ap->a_vp)->fd_type) { | |
732 | case Fctty: | |
733 | error = cttyselect(devctty, ap->a_fflags, ap->a_p); | |
734 | break; | |
735 | ||
736 | default: | |
737 | error = EOPNOTSUPP; | |
738 | break; | |
739 | } | |
740 | ||
741 | return (error); | |
742 | } | |
743 | ||
43ec9518 | 744 | int |
5e3f92c4 KM |
745 | fdesc_inactive(ap) |
746 | struct vop_inactive_args /* { | |
747 | struct vnode *a_vp; | |
748 | } */ *ap; | |
e2e9adba | 749 | { |
a02db9dd JSP |
750 | struct vnode *vp = ap->a_vp; |
751 | ||
e2e9adba JSP |
752 | /* |
753 | * Clear out the v_type field to avoid | |
754 | * nasty things happening in vgone(). | |
755 | */ | |
a02db9dd | 756 | vp->v_type = VNON; |
e2e9adba JSP |
757 | return (0); |
758 | } | |
759 | ||
43ec9518 | 760 | int |
5e3f92c4 KM |
761 | fdesc_reclaim(ap) |
762 | struct vop_reclaim_args /* { | |
763 | struct vnode *a_vp; | |
764 | } */ *ap; | |
e2e9adba JSP |
765 | { |
766 | struct vnode *vp = ap->a_vp; | |
01936f59 | 767 | |
43ec9518 JSP |
768 | remque(VTOFDESC(vp)); |
769 | FREE(vp->v_data, M_TEMP); | |
770 | vp->v_data = 0; | |
771 | ||
e2e9adba JSP |
772 | return (0); |
773 | } | |
774 | ||
775 | /* | |
776 | * Print out the contents of a /dev/fd vnode. | |
777 | */ | |
778 | /* ARGSUSED */ | |
43ec9518 | 779 | int |
5e3f92c4 KM |
780 | fdesc_print(ap) |
781 | struct vop_print_args /* { | |
782 | struct vnode *a_vp; | |
783 | } */ *ap; | |
e2e9adba | 784 | { |
5e3f92c4 | 785 | |
e2e9adba | 786 | printf("tag VT_NON, fdesc vnode\n"); |
5e3f92c4 | 787 | return (0); |
e2e9adba JSP |
788 | } |
789 | ||
790 | /*void*/ | |
43ec9518 | 791 | int |
5e3f92c4 KM |
792 | fdesc_vfree(ap) |
793 | struct vop_vfree_args /* { | |
794 | struct vnode *a_pvp; | |
795 | ino_t a_ino; | |
796 | int a_mode; | |
797 | } */ *ap; | |
e2e9adba JSP |
798 | { |
799 | ||
5e3f92c4 | 800 | return (0); |
e2e9adba JSP |
801 | } |
802 | ||
803 | /* | |
804 | * /dev/fd vnode unsupported operation | |
805 | */ | |
43ec9518 | 806 | int |
e2e9adba JSP |
807 | fdesc_enotsupp() |
808 | { | |
5e3f92c4 | 809 | |
e2e9adba JSP |
810 | return (EOPNOTSUPP); |
811 | } | |
812 | ||
813 | /* | |
814 | * /dev/fd "should never get here" operation | |
815 | */ | |
43ec9518 | 816 | int |
e2e9adba JSP |
817 | fdesc_badop() |
818 | { | |
5e3f92c4 | 819 | |
e2e9adba JSP |
820 | panic("fdesc: bad op"); |
821 | /* NOTREACHED */ | |
822 | } | |
823 | ||
824 | /* | |
825 | * /dev/fd vnode null operation | |
826 | */ | |
43ec9518 | 827 | int |
e2e9adba JSP |
828 | fdesc_nullop() |
829 | { | |
5e3f92c4 | 830 | |
e2e9adba JSP |
831 | return (0); |
832 | } | |
833 | ||
834 | #define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp) | |
835 | #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp) | |
836 | #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop) | |
837 | #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop) | |
e2e9adba JSP |
838 | #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp) |
839 | #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) | |
840 | #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop) | |
841 | #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp) | |
842 | #define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp) | |
843 | #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp) | |
844 | #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp) | |
845 | #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp) | |
5e3f92c4 | 846 | #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp) |
e2e9adba JSP |
847 | #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) |
848 | #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop) | |
849 | #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) | |
850 | #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop) | |
851 | #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop) | |
852 | #define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) | |
5e3f92c4 | 853 | #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp) |
b076d1ce | 854 | #define fdesc_blkatoff \ |
5e3f92c4 | 855 | ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp) |
e2e9adba JSP |
856 | #define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp) |
857 | #define fdesc_valloc ((int(*) __P(( \ | |
858 | struct vnode *pvp, \ | |
859 | int mode, \ | |
860 | struct ucred *cred, \ | |
861 | struct vnode **vpp))) fdesc_enotsupp) | |
b076d1ce | 862 | #define fdesc_truncate \ |
5e3f92c4 | 863 | ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp) |
e2e9adba JSP |
864 | #define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp) |
865 | #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp) | |
866 | ||
867 | int (**fdesc_vnodeop_p)(); | |
868 | struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = { | |
869 | { &vop_default_desc, vn_default_error }, | |
870 | { &vop_lookup_desc, fdesc_lookup }, /* lookup */ | |
871 | { &vop_create_desc, fdesc_create }, /* create */ | |
872 | { &vop_mknod_desc, fdesc_mknod }, /* mknod */ | |
5e3f92c4 | 873 | { &vop_open_desc, fdesc_open }, /* open */ |
e2e9adba JSP |
874 | { &vop_close_desc, fdesc_close }, /* close */ |
875 | { &vop_access_desc, fdesc_access }, /* access */ | |
876 | { &vop_getattr_desc, fdesc_getattr }, /* getattr */ | |
877 | { &vop_setattr_desc, fdesc_setattr }, /* setattr */ | |
5e3f92c4 | 878 | { &vop_read_desc, fdesc_read }, /* read */ |
e2e9adba JSP |
879 | { &vop_write_desc, fdesc_write }, /* write */ |
880 | { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ | |
881 | { &vop_select_desc, fdesc_select }, /* select */ | |
5e3f92c4 | 882 | { &vop_mmap_desc, fdesc_mmap }, /* mmap */ |
e2e9adba | 883 | { &vop_fsync_desc, fdesc_fsync }, /* fsync */ |
5e3f92c4 | 884 | { &vop_seek_desc, fdesc_seek }, /* seek */ |
e2e9adba | 885 | { &vop_remove_desc, fdesc_remove }, /* remove */ |
5e3f92c4 | 886 | { &vop_link_desc, fdesc_link }, /* link */ |
e2e9adba JSP |
887 | { &vop_rename_desc, fdesc_rename }, /* rename */ |
888 | { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */ | |
889 | { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */ | |
890 | { &vop_symlink_desc, fdesc_symlink }, /* symlink */ | |
891 | { &vop_readdir_desc, fdesc_readdir }, /* readdir */ | |
892 | { &vop_readlink_desc, fdesc_readlink }, /* readlink */ | |
893 | { &vop_abortop_desc, fdesc_abortop }, /* abortop */ | |
894 | { &vop_inactive_desc, fdesc_inactive }, /* inactive */ | |
895 | { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */ | |
5e3f92c4 | 896 | { &vop_lock_desc, fdesc_lock }, /* lock */ |
e2e9adba | 897 | { &vop_unlock_desc, fdesc_unlock }, /* unlock */ |
5e3f92c4 | 898 | { &vop_bmap_desc, fdesc_bmap }, /* bmap */ |
e2e9adba JSP |
899 | { &vop_strategy_desc, fdesc_strategy }, /* strategy */ |
900 | { &vop_print_desc, fdesc_print }, /* print */ | |
901 | { &vop_islocked_desc, fdesc_islocked }, /* islocked */ | |
902 | { &vop_advlock_desc, fdesc_advlock }, /* advlock */ | |
903 | { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */ | |
e2e9adba JSP |
904 | { &vop_valloc_desc, fdesc_valloc }, /* valloc */ |
905 | { &vop_vfree_desc, fdesc_vfree }, /* vfree */ | |
906 | { &vop_truncate_desc, fdesc_truncate }, /* truncate */ | |
907 | { &vop_update_desc, fdesc_update }, /* update */ | |
908 | { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */ | |
909 | { (struct vnodeop_desc*)NULL, (int(*)())NULL } | |
910 | }; | |
911 | struct vnodeopv_desc fdesc_vnodeop_opv_desc = | |
912 | { &fdesc_vnodeop_p, fdesc_vnodeop_entries }; |