]> git.saurik.com Git - apple/xnu.git/blame - bsd/miscfs/fdesc/fdesc_vnops.c
xnu-792.17.14.tar.gz
[apple/xnu.git] / bsd / miscfs / fdesc / fdesc_vnops.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29/*
30 * Copyright (c) 1992, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * This code is derived from software donated to Berkeley by
34 * Jan-Simon Pendry.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95
65 *
66 */
67
68/*
69 * /dev/fd Filesystem
70 */
71
72#include <sys/param.h>
73#include <sys/systm.h>
74#include <sys/types.h>
75#include <sys/time.h>
91447636 76#include <sys/proc_internal.h>
1c79356b
A
77#include <sys/kernel.h> /* boottime */
78#include <sys/resourcevar.h>
79#include <sys/filedesc.h>
91447636
A
80#include <sys/kauth.h>
81#include <sys/vnode_internal.h>
1c79356b 82#include <sys/malloc.h>
91447636 83#include <sys/file_internal.h>
1c79356b 84#include <sys/stat.h>
91447636 85#include <sys/mount_internal.h>
1c79356b 86#include <sys/namei.h>
1c79356b
A
87#include <sys/dirent.h>
88#include <sys/ubc.h>
91447636
A
89#include <sys/socketvar.h>
90#include <sys/pipe.h>
91#include <sys/uio_internal.h>
1c79356b
A
92#include <miscfs/fdesc/fdesc.h>
93#include <vfs/vfs_support.h>
91447636 94#include <pexpert/pexpert.h>
1c79356b 95
1c79356b
A
96#define FDL_WANT 0x01
97#define FDL_LOCKED 0x02
98static int fdcache_lock;
99
1c79356b
A
100
101#if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
102FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
103#endif
104
9bccf70c 105#define NFDCACHE 3
1c79356b
A
106
107#define FD_NHASH(ix) \
108 (&fdhashtbl[(ix) & fdhash])
109LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
110u_long fdhash;
111
91447636
A
112static int fdesc_attr(int fd, struct vnode_attr *vap, vfs_context_t a_context);
113
114
1c79356b
A
115/*
116 * Initialise cache headers
117 */
91447636
A
118int
119fdesc_init(__unused struct vfsconf *vfsp)
1c79356b
A
120{
121
1c79356b 122 fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
91447636
A
123
124 return( 0 );
1c79356b
A
125}
126
127int
91447636 128fdesc_allocvp(ftype, ix, mp, vpp, vtype)
1c79356b
A
129 fdntype ftype;
130 int ix;
131 struct mount *mp;
132 struct vnode **vpp;
91447636 133 enum vtype vtype;
1c79356b 134{
1c79356b
A
135 struct fdhashhead *fc;
136 struct fdescnode *fd;
137 int error = 0;
91447636
A
138 int vid = 0;
139 struct vnode_fsparam vfsp;
1c79356b
A
140
141 fc = FD_NHASH(ix);
142loop:
143 for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
91447636
A
144 if (fd->fd_ix == ix && vnode_mount(fd->fd_vnode) == mp) {
145 /*
146 * doing a vnode_getwithvid isn't technically
147 * necessary since fdesc is an unsafe filesystem
148 * and we're running behind a funnel at this point
149 * however, vnode_get always succeeds, which isn't
150 * what we want if this vnode is in the process of
151 * being terminated
152 */
153 vid = vnode_vid(fd->fd_vnode);
154
155 if (vnode_getwithvid(fd->fd_vnode, vid))
1c79356b
A
156 goto loop;
157 *vpp = fd->fd_vnode;
91447636
A
158 (*vpp)->v_type = vtype;
159
1c79356b
A
160 return (error);
161 }
162 }
163
164 /*
165 * otherwise lock the array while we call getnewvnode
166 * since that can block.
167 */
168 if (fdcache_lock & FDL_LOCKED) {
169 fdcache_lock |= FDL_WANT;
170 sleep((caddr_t) &fdcache_lock, PINOD);
171 goto loop;
172 }
173 fdcache_lock |= FDL_LOCKED;
174
175 MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK);
91447636
A
176
177 vfsp.vnfs_mp = mp;
178 vfsp.vnfs_vtype = vtype;
179 vfsp.vnfs_str = "fdesc";
180 vfsp.vnfs_dvp = 0;
181 vfsp.vnfs_fsnode = fd;
182 vfsp.vnfs_cnp = 0;
183 vfsp.vnfs_vops = fdesc_vnodeop_p;
184 vfsp.vnfs_rdev = 0;
185 vfsp.vnfs_filesize = 0;
186 vfsp.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE;
187 vfsp.vnfs_marksystem = 0;
188 if (ftype == Froot)
189 vfsp.vnfs_markroot = 1;
190 else
191 vfsp.vnfs_markroot = 0;
192
193 error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vfsp, vpp);
1c79356b
A
194 if (error) {
195 FREE(fd, M_TEMP);
196 goto out;
197 }
91447636 198 (*vpp)->v_tag = VT_FDESC;
1c79356b
A
199 fd->fd_vnode = *vpp;
200 fd->fd_type = ftype;
201 fd->fd_fd = -1;
202 fd->fd_link = 0;
203 fd->fd_ix = ix;
204 LIST_INSERT_HEAD(fc, fd, fd_hash);
205
206out:
207 fdcache_lock &= ~FDL_LOCKED;
208
209 if (fdcache_lock & FDL_WANT) {
210 fdcache_lock &= ~FDL_WANT;
211 wakeup((caddr_t) &fdcache_lock);
212 }
213
214 return (error);
215}
216
217/*
218 * vp is the current namei directory
219 * ndp is the name to locate in that directory...
220 */
221int
222fdesc_lookup(ap)
91447636 223 struct vnop_lookup_args /* {
1c79356b
A
224 struct vnode * a_dvp;
225 struct vnode ** a_vpp;
226 struct componentname * a_cnp;
91447636 227 vfs_context_t a_context;
1c79356b
A
228 } */ *ap;
229{
230 struct vnode **vpp = ap->a_vpp;
231 struct vnode *dvp = ap->a_dvp;
232 struct componentname *cnp = ap->a_cnp;
233 char *pname = cnp->cn_nameptr;
91447636
A
234 struct proc *p = vfs_context_proc(ap->a_context);
235 int numfiles = p->p_fd->fd_nfiles;
236 int fd;
1c79356b
A
237 int error;
238 struct vnode *fvp;
239 char *ln;
240
1c79356b
A
241 if (cnp->cn_namelen == 1 && *pname == '.') {
242 *vpp = dvp;
91447636
A
243
244 if ( (error = vnode_get(dvp)) ) {
245 return(error);
246 }
1c79356b
A
247 return (0);
248 }
249
250 switch (VTOFDESC(dvp)->fd_type) {
251 default:
252 case Flink:
253 case Fdesc:
91447636 254 /* should never happen */
1c79356b
A
255 error = ENOTDIR;
256 goto bad;
257
258 case Froot:
259 if (cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
91447636 260 error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp, VDIR);
1c79356b
A
261 if (error)
262 goto bad;
263 *vpp = fvp;
1c79356b
A
264 return (0);
265 }
266
91447636 267 ln = NULL;
1c79356b
A
268 switch (cnp->cn_namelen) {
269 case 5:
270 if (bcmp(pname, "stdin", 5) == 0) {
271 ln = "fd/0";
272 fd = FD_STDIN;
273 }
274 break;
275 case 6:
276 if (bcmp(pname, "stdout", 6) == 0) {
277 ln = "fd/1";
278 fd = FD_STDOUT;
279 } else
280 if (bcmp(pname, "stderr", 6) == 0) {
281 ln = "fd/2";
282 fd = FD_STDERR;
283 }
284 break;
285 }
286
287 if (ln) {
91447636 288 error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp, VLNK);
1c79356b
A
289 if (error)
290 goto bad;
291 VTOFDESC(fvp)->fd_link = ln;
292 *vpp = fvp;
1c79356b
A
293 return (0);
294 } else {
295 error = ENOENT;
296 goto bad;
297 }
298
299 /* FALL THROUGH */
300
301 case Fdevfd:
302 if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
91447636 303 if ((error = fdesc_root(dvp->v_mount, vpp, ap->a_context)))
1c79356b
A
304 goto bad;
305 return (0);
306 }
307
308 fd = 0;
309 while (*pname >= '0' && *pname <= '9') {
310 fd = 10 * fd + *pname++ - '0';
91447636 311 if (fd >= numfiles)
1c79356b
A
312 break;
313 }
314
315 if (*pname != '\0') {
316 error = ENOENT;
317 goto bad;
318 }
319
91447636 320 if (fd < 0 || fd >= numfiles ||
1c79356b
A
321 *fdfile(p, fd) == NULL ||
322 (*fdflags(p, fd) & UF_RESERVED)) {
323 error = EBADF;
324 goto bad;
325 }
326
91447636 327 error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp, VNON);
1c79356b
A
328 if (error)
329 goto bad;
330 VTOFDESC(fvp)->fd_fd = fd;
1c79356b
A
331 *vpp = fvp;
332 return (0);
333 }
334
335bad:;
1c79356b
A
336 *vpp = NULL;
337 return (error);
338}
339
340int
341fdesc_open(ap)
91447636 342 struct vnop_open_args /* {
1c79356b
A
343 struct vnode *a_vp;
344 int a_mode;
91447636 345 vfs_context_t a_context;
1c79356b
A
346 } */ *ap;
347{
348 struct vnode *vp = ap->a_vp;
91447636 349 struct proc *p = vfs_context_proc(ap->a_context);
1c79356b
A
350 int error = 0;
351
352 switch (VTOFDESC(vp)->fd_type) {
353 case Fdesc:
354 /*
355 * XXX Kludge: set p->p_dupfd to contain the value of the
356 * the file descriptor being sought for duplication. The error
357 * return ensures that the vnode for this device will be
358 * released by vn_open. Open will detect this special error and
359 * take the actions in dupfdopen. Other callers of vn_open or
91447636 360 * vnop_open will simply report the error.
1c79356b 361 */
91447636 362 p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */
1c79356b
A
363 error = ENODEV;
364 break;
365
1c79356b
A
366 }
367
368 return (error);
369}
370
371static int
91447636 372fdesc_attr(int fd, struct vnode_attr *vap, vfs_context_t a_context)
1c79356b 373{
91447636
A
374 struct fileproc *fp;
375 struct proc *p = vfs_context_proc(a_context);
1c79356b
A
376 struct stat stb;
377 int error;
378
91447636 379 if ((error = fp_lookup(p, fd, &fp, 0)))
1c79356b 380 return (error);
91447636 381 switch (fp->f_fglob->fg_type) {
1c79356b 382 case DTYPE_VNODE:
91447636
A
383 if(error = vnode_getwithref((struct vnode *) fp->f_fglob->fg_data)) {
384 break;
385 }
386 if ((error = vnode_authorize((struct vnode *)fp->f_fglob->fg_data,
387 NULL,
388 KAUTH_VNODE_READ_ATTRIBUTES | KAUTH_VNODE_READ_SECURITY,
389 a_context)) == 0)
390 error = vnode_getattr((struct vnode *)fp->f_fglob->fg_data, vap, a_context);
1c79356b
A
391 if (error == 0 && vap->va_type == VDIR) {
392 /*
393 * directories can cause loops in the namespace,
394 * so turn off the 'x' bits to avoid trouble.
91447636
A
395 *
396 * XXX ACLs break this, of course
1c79356b
A
397 */
398 vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6));
399 }
91447636 400 (void)vnode_put((struct vnode *) fp->f_fglob->fg_data);
1c79356b
A
401 break;
402
403 case DTYPE_SOCKET:
91447636
A
404 case DTYPE_PIPE:
405 if (fp->f_fglob->fg_type == DTYPE_SOCKET)
406 error = soo_stat((struct socket *)fp->f_fglob->fg_data, &stb);
407 else
408 error = pipe_stat((struct socket *)fp->f_fglob->fg_data, &stb);
409
1c79356b 410 if (error == 0) {
91447636
A
411 if (fp->f_fglob->fg_type == DTYPE_SOCKET)
412 VATTR_RETURN(vap, va_type, VSOCK);
413 else
414 VATTR_RETURN(vap, va_type, VFIFO);
415
416 VATTR_RETURN(vap, va_mode, stb.st_mode);
417 VATTR_RETURN(vap, va_nlink, stb.st_nlink);
418 VATTR_RETURN(vap, va_uid, stb.st_uid);
419 VATTR_RETURN(vap, va_gid, stb.st_gid);
420 VATTR_RETURN(vap, va_fsid, stb.st_dev);
421 VATTR_RETURN(vap, va_fileid, stb.st_ino);
422 VATTR_RETURN(vap, va_data_size, stb.st_size);
423 VATTR_RETURN(vap, va_access_time, stb.st_atimespec);
424 VATTR_RETURN(vap, va_modify_time, stb.st_mtimespec);
425 VATTR_RETURN(vap, va_change_time, stb.st_ctimespec);
426 VATTR_RETURN(vap, va_gen, stb.st_gen);
427 VATTR_RETURN(vap, va_flags, stb.st_flags);
428 VATTR_RETURN(vap, va_rdev, stb.st_rdev);
429 VATTR_RETURN(vap, va_total_alloc, stb.st_blocks * stb.st_blksize);
430 VATTR_RETURN(vap, va_acl, NULL);
1c79356b
A
431 }
432 break;
433
434 default:
91447636 435 error = EBADF;
1c79356b
A
436 }
437
91447636 438 fp_drop(p, fd, fp, 0);
1c79356b
A
439 return (error);
440}
441
442int
443fdesc_getattr(ap)
91447636 444 struct vnop_getattr_args /* {
1c79356b 445 struct vnode *a_vp;
91447636
A
446 struct vnode_attr *a_vap;
447 vfs_context_t a_context;
1c79356b
A
448 } */ *ap;
449{
450 struct vnode *vp = ap->a_vp;
91447636 451 struct vnode_attr *vap = ap->a_vap;
1c79356b
A
452 unsigned fd;
453 int error = 0;
91447636 454 struct timespec ts;
1c79356b
A
455
456 switch (VTOFDESC(vp)->fd_type) {
457 case Froot:
458 case Fdevfd:
459 case Flink:
91447636
A
460 VATTR_RETURN(vap, va_fileid, VTOFDESC(vp)->fd_ix);
461 VATTR_RETURN(vap, va_uid, 0);
462 VATTR_RETURN(vap, va_gid, 0);
463 VATTR_RETURN(vap, va_fsid, vp->v_mount->mnt_vfsstat.f_fsid.val[0]);
464 VATTR_RETURN(vap, va_iosize, DEV_BSIZE);
465 ts.tv_sec = boottime_sec();
466 ts.tv_nsec = 0;
467 VATTR_RETURN(vap, va_access_time, ts);
468 VATTR_RETURN(vap, va_modify_time, ts);
469 VATTR_RETURN(vap, va_change_time, ts);
470 VATTR_RETURN(vap, va_gen, 0);
471 VATTR_RETURN(vap, va_flags, 0);
472 VATTR_RETURN(vap, va_rdev, 0);
473 VATTR_RETURN(vap, va_acl, NULL);
1c79356b
A
474
475 switch (VTOFDESC(vp)->fd_type) {
476 case Flink:
91447636
A
477 VATTR_RETURN(vap, va_mode, S_IRUSR|S_IRGRP|S_IROTH);
478 VATTR_RETURN(vap, va_type, VLNK); /* not strictly required */
479 VATTR_RETURN(vap, va_nlink, 1);
480 VATTR_RETURN(vap, va_data_size, strlen(VTOFDESC(vp)->fd_link));
1c79356b
A
481 break;
482
1c79356b 483 default:
91447636
A
484 VATTR_RETURN(vap, va_mode, S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
485 VATTR_RETURN(vap, va_type, VDIR);
486 VATTR_RETURN(vap, va_nlink, 2);
487 VATTR_RETURN(vap, va_data_size, DEV_BSIZE);
1c79356b
A
488 break;
489 }
490 break;
491
492 case Fdesc:
493 fd = VTOFDESC(vp)->fd_fd;
91447636 494 error = fdesc_attr(fd, vap, ap->a_context);
1c79356b
A
495 break;
496
497 default:
9bccf70c 498 return (EBADF);
1c79356b
A
499 break;
500 }
91447636 501
1c79356b
A
502 if (error == 0) {
503 vp->v_type = vap->va_type;
504 }
505
506 return (error);
507}
508
509int
510fdesc_setattr(ap)
91447636 511 struct vnop_setattr_args /* {
1c79356b 512 struct vnode *a_vp;
91447636
A
513 struct vnode_attr *a_vap;
514 vfs_context_t a_context;
1c79356b
A
515 } */ *ap;
516{
91447636 517 struct fileproc *fp;
1c79356b
A
518 unsigned fd;
519 int error;
91447636 520 struct proc * p = vfs_context_proc(ap->a_context);
1c79356b
A
521
522 /*
523 * Can't mess with the root vnode
524 */
525 switch (VTOFDESC(ap->a_vp)->fd_type) {
526 case Fdesc:
527 break;
528
1c79356b
A
529 default:
530 return (EACCES);
531 }
532
533 fd = VTOFDESC(ap->a_vp)->fd_fd;
91447636 534 if ((error = fp_lookup(vfs_context_proc(ap->a_context), fd, &fp, 0)))
1c79356b
A
535 return (error);
536
537 /*
538 * Can setattr the underlying vnode, but not sockets!
539 */
91447636 540 switch (fp->f_fglob->fg_type) {
1c79356b 541 case DTYPE_VNODE:
91447636
A
542 {
543 if ((error = vnode_getwithref((struct vnode *) fp->f_fglob->fg_data)) != 0)
544 break;
545 error = vnode_setattr((struct vnode *) fp->f_fglob->fg_data, ap->a_vap, ap->a_context);
546 (void)vnode_put((struct vnode *) fp->f_fglob->fg_data);
1c79356b 547 break;
91447636 548 }
1c79356b
A
549
550 case DTYPE_SOCKET:
91447636 551 case DTYPE_PIPE:
1c79356b
A
552 error = 0;
553 break;
554
555 default:
91447636 556 kprintf("fp->f_fglob->fg_type = %d\n", fp->f_fglob->fg_type);
1c79356b
A
557 error = EBADF;
558 break;
559 }
560
91447636 561 fp_drop(p, fd, fp, 0);
1c79356b
A
562 return (error);
563}
564
565#define UIO_MX 16
566
567static struct dirtmp {
568 u_long d_fileno;
569 u_short d_reclen;
570 u_short d_namlen;
571 char d_name[8];
572} rootent[] = {
573 { FD_DEVFD, UIO_MX, 2, "fd" },
574 { FD_STDIN, UIO_MX, 5, "stdin" },
575 { FD_STDOUT, UIO_MX, 6, "stdout" },
576 { FD_STDERR, UIO_MX, 6, "stderr" },
91447636 577 { 0, 0, 0, "" }
1c79356b
A
578};
579
580int
581fdesc_readdir(ap)
91447636 582 struct vnop_readdir_args /* {
1c79356b
A
583 struct vnode *a_vp;
584 struct uio *a_uio;
91447636 585 int a_flags;
1c79356b 586 int *a_eofflag;
91447636
A
587 int *a_numdirent;
588 vfs_context_t a_context;
1c79356b
A
589 } */ *ap;
590{
591 struct uio *uio = ap->a_uio;
91447636 592 struct proc *p = current_proc();
1c79356b
A
593 int i, error;
594
595 /*
596 * We don't allow exporting fdesc mounts, and currently local
597 * requests do not need cookies.
598 */
91447636 599 if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
9bccf70c 600 return (EINVAL);
1c79356b
A
601
602 switch (VTOFDESC(ap->a_vp)->fd_type) {
1c79356b
A
603 case Fdesc:
604 return (ENOTDIR);
605
606 default:
607 break;
608 }
609
610 if (VTOFDESC(ap->a_vp)->fd_type == Froot) {
611 struct dirent d;
612 struct dirent *dp = &d;
613 struct dirtmp *dt;
614 int fd;
615
616 i = uio->uio_offset / UIO_MX;
617 error = 0;
618
91447636 619 while (uio_resid(uio) > 0) {
1c79356b
A
620 dt = &rootent[i];
621 if (dt->d_fileno == 0) {
622 /**eofflagp = 1;*/
623 break;
624 }
625 i++;
626
627 switch (dt->d_fileno) {
1c79356b
A
628 case FD_STDIN:
629 case FD_STDOUT:
630 case FD_STDERR:
631 fd = dt->d_fileno - FD_STDIN;
632 if (fd >= p->p_fd->fd_nfiles)
633 continue;
634 if (*fdfile(p, fd) == NULL &&
635 !(*fdflags(p, fd) &
636 UF_RESERVED))
637 continue;
638 break;
639 }
640 bzero((caddr_t) dp, UIO_MX);
641 dp->d_fileno = dt->d_fileno;
642 dp->d_namlen = dt->d_namlen;
643 dp->d_type = DT_UNKNOWN;
644 dp->d_reclen = dt->d_reclen;
645 bcopy(dt->d_name, dp->d_name, dp->d_namlen+1);
646 error = uiomove((caddr_t) dp, UIO_MX, uio);
647 if (error)
648 break;
649 }
650 uio->uio_offset = i * UIO_MX;
651 return (error);
652 }
653
654 i = uio->uio_offset / UIO_MX;
655 error = 0;
91447636 656 while (uio_resid(uio) > 0) {
1c79356b
A
657 if (i >= p->p_fd->fd_nfiles)
658 break;
659
660 if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) {
661 struct dirent d;
662 struct dirent *dp = &d;
663
664 bzero((caddr_t) dp, UIO_MX);
665
666 dp->d_namlen = sprintf(dp->d_name, "%d", i);
667 dp->d_reclen = UIO_MX;
668 dp->d_type = DT_UNKNOWN;
669 dp->d_fileno = i + FD_STDIN;
670 /*
671 * And ship to userland
672 */
673 error = uiomove((caddr_t) dp, UIO_MX, uio);
674 if (error)
675 break;
676 }
677 i++;
678 }
679
680 uio->uio_offset = i * UIO_MX;
681 return (error);
682}
683
684int
685fdesc_readlink(ap)
91447636 686 struct vnop_readlink_args /* {
1c79356b
A
687 struct vnode *a_vp;
688 struct uio *a_uio;
91447636 689 vfs_context_t a_context;
1c79356b
A
690 } */ *ap;
691{
692 struct vnode *vp = ap->a_vp;
693 int error;
694
695 if (vp->v_type != VLNK)
696 return (EPERM);
697
698 if (VTOFDESC(vp)->fd_type == Flink) {
699 char *ln = VTOFDESC(vp)->fd_link;
700 error = uiomove(ln, strlen(ln), ap->a_uio);
701 } else {
91447636 702 error = ENOTSUP;
1c79356b
A
703 }
704
705 return (error);
706}
707
708int
91447636 709fdesc_read(__unused struct vnop_read_args *ap)
1c79356b 710{
1c79356b 711
91447636 712 return (ENOTSUP);
1c79356b
A
713}
714
715int
91447636 716fdesc_write(__unused struct vnop_write_args *ap)
1c79356b 717{
91447636 718 return (ENOTSUP);
1c79356b
A
719}
720
721int
91447636 722fdesc_ioctl(__unused struct vnop_ioctl_args *ap)
1c79356b 723{
91447636 724 return (ENOTSUP);
1c79356b
A
725}
726
727int
91447636 728fdesc_select(__unused struct vnop_select_args *ap)
1c79356b 729{
91447636 730 return (ENOTSUP);
1c79356b
A
731}
732
733int
734fdesc_inactive(ap)
91447636 735 struct vnop_inactive_args /* {
1c79356b 736 struct vnode *a_vp;
91447636 737 vfs_context_t a_context;
1c79356b
A
738 } */ *ap;
739{
740 struct vnode *vp = ap->a_vp;
741
742 /*
743 * Clear out the v_type field to avoid
744 * nasty things happening in vgone().
745 */
1c79356b
A
746 vp->v_type = VNON;
747 return (0);
748}
749
750int
751fdesc_reclaim(ap)
91447636 752 struct vnop_reclaim_args /* {
1c79356b 753 struct vnode *a_vp;
91447636 754 vfs_context_t a_context;
1c79356b
A
755 } */ *ap;
756{
757 struct vnode *vp = ap->a_vp;
758 struct fdescnode *fd = VTOFDESC(vp);
759
760 LIST_REMOVE(fd, fd_hash);
761 FREE(vp->v_data, M_TEMP);
762 vp->v_data = 0;
763
764 return (0);
765}
766
767/*
768 * Return POSIX pathconf information applicable to special devices.
769 */
91447636 770int
1c79356b 771fdesc_pathconf(ap)
91447636 772 struct vnop_pathconf_args /* {
1c79356b
A
773 struct vnode *a_vp;
774 int a_name;
775 int *a_retval;
91447636 776 vfs_context_t a_context;
1c79356b
A
777 } */ *ap;
778{
779
780 switch (ap->a_name) {
781 case _PC_LINK_MAX:
782 *ap->a_retval = LINK_MAX;
783 return (0);
784 case _PC_MAX_CANON:
785 *ap->a_retval = MAX_CANON;
786 return (0);
787 case _PC_MAX_INPUT:
788 *ap->a_retval = MAX_INPUT;
789 return (0);
790 case _PC_PIPE_BUF:
791 *ap->a_retval = PIPE_BUF;
792 return (0);
793 case _PC_CHOWN_RESTRICTED:
794 *ap->a_retval = 1;
795 return (0);
796 case _PC_VDISABLE:
797 *ap->a_retval = _POSIX_VDISABLE;
798 return (0);
799 default:
800 return (EINVAL);
801 }
802 /* NOTREACHED */
803}
804
1c79356b
A
805
806/*void*/
807int
91447636 808fdesc_vfree(__unused struct vnop_vfree_args *ap)
1c79356b
A
809{
810
811 return (0);
812}
813
814/*
815 * /dev/fd "should never get here" operation
816 */
817int
91447636 818fdesc_badop(void)
1c79356b
A
819{
820
9bccf70c 821 return (ENOTSUP);
1c79356b
A
822 /* NOTREACHED */
823}
824
825#define VOPFUNC int (*)(void *)
826
91447636
A
827#define fdesc_create (int (*) (struct vnop_create_args *))eopnotsupp
828#define fdesc_mknod (int (*) (struct vnop_mknod_args *))eopnotsupp
829#define fdesc_close (int (*) (struct vnop_close_args *))nullop
830#define fdesc_access (int (*) (struct vnop_access_args *))nullop
831#define fdesc_mmap (int (*) (struct vnop_mmap_args *))eopnotsupp
832#define fdesc_revoke nop_revoke
833#define fdesc_fsync (int (*) (struct vnop_fsync_args *))nullop
834#define fdesc_remove (int (*) (struct vnop_remove_args *))eopnotsupp
835#define fdesc_link (int (*) (struct vnop_link_args *))eopnotsupp
836#define fdesc_rename (int (*) (struct vnop_rename_args *))eopnotsupp
837#define fdesc_mkdir (int (*) (struct vnop_mkdir_args *))eopnotsupp
838#define fdesc_rmdir (int (*) (struct vnop_rmdir_args *))eopnotsupp
839#define fdesc_symlink (int (*) (struct vnop_symlink_args *))eopnotsupp
840#define fdesc_strategy (int (*) (struct vnop_strategy_args *))fdesc_badop
841#define fdesc_advlock (int (*) (struct vnop_advlock_args *))eopnotsupp
842#define fdesc_bwrite (int (*) (struct vnop_bwrite_args *))eopnotsupp
843#define fdesc_blktooff (int (*) (struct vnop_blktooff_args *))eopnotsupp
844#define fdesc_offtoblk (int (*) (struct vnop_offtoblk_args *))eopnotsupp
845#define fdesc_blockmap (int (*) (struct vnop_blockmap_args *))eopnotsupp
1c79356b
A
846
847int (**fdesc_vnodeop_p)(void *);
848struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
91447636
A
849 { &vnop_default_desc, (VOPFUNC)vn_default_error },
850 { &vnop_lookup_desc, (VOPFUNC)fdesc_lookup }, /* lookup */
851 { &vnop_create_desc, (VOPFUNC)fdesc_create }, /* create */
852 { &vnop_mknod_desc, (VOPFUNC)fdesc_mknod }, /* mknod */
853 { &vnop_open_desc, (VOPFUNC)fdesc_open }, /* open */
854 { &vnop_close_desc, (VOPFUNC)fdesc_close }, /* close */
855 { &vnop_access_desc, (VOPFUNC)fdesc_access }, /* access */
856 { &vnop_getattr_desc, (VOPFUNC)fdesc_getattr }, /* getattr */
857 { &vnop_setattr_desc, (VOPFUNC)fdesc_setattr }, /* setattr */
858 { &vnop_read_desc, (VOPFUNC)fdesc_read }, /* read */
859 { &vnop_write_desc, (VOPFUNC)fdesc_write }, /* write */
860 { &vnop_ioctl_desc, (VOPFUNC)fdesc_ioctl }, /* ioctl */
861 { &vnop_select_desc, (VOPFUNC)fdesc_select }, /* select */
862 { &vnop_revoke_desc, (VOPFUNC)fdesc_revoke }, /* revoke */
863 { &vnop_mmap_desc, (VOPFUNC)fdesc_mmap }, /* mmap */
864 { &vnop_fsync_desc, (VOPFUNC)fdesc_fsync }, /* fsync */
865 { &vnop_remove_desc, (VOPFUNC)fdesc_remove }, /* remove */
866 { &vnop_link_desc, (VOPFUNC)fdesc_link }, /* link */
867 { &vnop_rename_desc, (VOPFUNC)fdesc_rename }, /* rename */
868 { &vnop_mkdir_desc, (VOPFUNC)fdesc_mkdir }, /* mkdir */
869 { &vnop_rmdir_desc, (VOPFUNC)fdesc_rmdir }, /* rmdir */
870 { &vnop_symlink_desc, (VOPFUNC)fdesc_symlink }, /* symlink */
871 { &vnop_readdir_desc, (VOPFUNC)fdesc_readdir }, /* readdir */
872 { &vnop_readlink_desc, (VOPFUNC)fdesc_readlink },/* readlink */
873 { &vnop_inactive_desc, (VOPFUNC)fdesc_inactive },/* inactive */
874 { &vnop_reclaim_desc, (VOPFUNC)fdesc_reclaim }, /* reclaim */
875 { &vnop_strategy_desc, (VOPFUNC)fdesc_strategy }, /* strategy */
876 { &vnop_pathconf_desc, (VOPFUNC)fdesc_pathconf }, /* pathconf */
877 { &vnop_advlock_desc, (VOPFUNC)fdesc_advlock }, /* advlock */
878 { &vnop_bwrite_desc, (VOPFUNC)fdesc_bwrite }, /* bwrite */
879 { &vnop_pagein_desc, (VOPFUNC)err_pagein }, /* pagein */
880 { &vnop_pageout_desc, (VOPFUNC)err_pageout }, /* pageout */
881 { &vnop_copyfile_desc, (VOPFUNC)err_copyfile }, /* Copyfile */
882 { &vnop_blktooff_desc, (VOPFUNC)fdesc_blktooff }, /* blktooff */
883 { &vnop_blktooff_desc, (VOPFUNC)fdesc_offtoblk }, /* offtoblk */
884 { &vnop_blockmap_desc, (VOPFUNC)fdesc_blockmap }, /* blockmap */
1c79356b
A
885 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL }
886};
887struct vnodeopv_desc fdesc_vnodeop_opv_desc =
888 { &fdesc_vnodeop_p, fdesc_vnodeop_entries };